diff --git a/SOURCES/0001-adapter-Don-t-refresh-adv_manager-for-non-LE-devices.patch b/SOURCES/0001-adapter-Don-t-refresh-adv_manager-for-non-LE-devices.patch new file mode 100644 index 0000000..46842c8 --- /dev/null +++ b/SOURCES/0001-adapter-Don-t-refresh-adv_manager-for-non-LE-devices.patch @@ -0,0 +1,51 @@ +From 2c3bba7b38be03834162e34069156f1fd49f0528 Mon Sep 17 00:00:00 2001 +From: "antoine.belvire@laposte.net" +Date: Tue, 27 Mar 2018 20:30:26 +0200 +Subject: [PATCH] adapter: Don't refresh adv_manager for non-LE devices + +btd_adv_manager_refresh is called upon MGMT_SETTING_DISCOVERABLE setting change +but as only LE adapters have an adv_manager, this leads to segmentation fault +for non-LE devices: + +0 btd_adv_manager_refresh (manager=0x0) at src/advertising.c:1176 +1 0x0000556fe45fcb02 in settings_changed (settings=, + adapter=0x556fe53f7c70) at src/adapter.c:543 +2 new_settings_callback (index=, length=, + param=, user_data=0x556fe53f7c70) at src/adapter.c:573 +3 0x0000556fe462c278 in request_complete (mgmt=mgmt@entry=0x556fe53f20c0, + status=, opcode=opcode@entry=7, index=index@entry=0, + length=length@entry=4, param=0x556fe53eb5f9) at src/shared/mgmt.c:261 +4 0x0000556fe462cd9d in can_read_data (io=, + user_data=0x556fe53f20c0) at src/shared/mgmt.c:353 +5 0x0000556fe46396e3 in watch_callback (channel=, + cond=, user_data=) + at src/shared/io-glib.c:170 +6 0x00007fe351c980e5 in g_main_context_dispatch () + from /usr/lib64/libglib-2.0.so.0 +7 0x00007fe351c984b0 in ?? () from /usr/lib64/libglib-2.0.so.0 +8 0x00007fe351c987c2 in g_main_loop_run () from /usr/lib64/libglib-2.0.so.0 +9 0x0000556fe45abc75 in main (argc=, argv=) + at src/main.c:770 + +This commit prevents the call to btd_adv_manager_refresh for non-LE devices. +--- + src/adapter.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/adapter.c b/src/adapter.c +index 6b9222bcf..daccfdc19 100644 +--- a/src/adapter.c ++++ b/src/adapter.c +@@ -540,7 +540,8 @@ static void settings_changed(struct btd_adapter *adapter, uint32_t settings) + g_dbus_emit_property_changed(dbus_conn, adapter->path, + ADAPTER_INTERFACE, "Discoverable"); + store_adapter_info(adapter); +- btd_adv_manager_refresh(adapter->adv_manager); ++ if (adapter->supported_settings & MGMT_SETTING_LE) ++ btd_adv_manager_refresh(adapter->adv_manager); + } + + if (changed_mask & MGMT_SETTING_BONDABLE) { +-- +2.17.0 + diff --git a/SOURCES/0001-hostname-Fix-BlueZ-5.XX-adapter-name-on-startup.patch b/SOURCES/0001-hostname-Fix-BlueZ-5.XX-adapter-name-on-startup.patch new file mode 100644 index 0000000..4caffdb --- /dev/null +++ b/SOURCES/0001-hostname-Fix-BlueZ-5.XX-adapter-name-on-startup.patch @@ -0,0 +1,38 @@ +From cba55944f76ad0f01bb7c8976fd6699f058c68cd Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 20 Sep 2017 14:42:14 +0200 +Subject: [PATCH] hostname: Fix "BlueZ 5.XX" adapter name on startup + +The hostname plugin listens to property changes from systemd-hostnamed +but doesn't fetch initial values. This means that unless the +PrettyHostname or StaticHostname changes, the default adapter will be +called "BlueZ 5.XX" matching the version number. + +This is the case since the hostname plugin replaced the adaptername +plugin in 2012. + +Fetch the initial values for PrettyHostname, StaticHostname and +Chassis when the plugin is initiated, so as to make the values +available for adapter setup. +--- + plugins/hostname.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/plugins/hostname.c b/plugins/hostname.c +index f876d0afb..db9187378 100644 +--- a/plugins/hostname.c ++++ b/plugins/hostname.c +@@ -307,6 +307,10 @@ static int hostname_init(void) + hostname_proxy = NULL; + g_dbus_client_unref(hostname_client); + hostname_client = NULL; ++ } else { ++ g_dbus_proxy_refresh_property(hostname_proxy, "PrettyHostname"); ++ g_dbus_proxy_refresh_property(hostname_proxy, "StaticHostname"); ++ g_dbus_proxy_refresh_property(hostname_proxy, "Chassis"); + } + + return err; +-- +2.14.1 + diff --git a/SOURCES/0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch b/SOURCES/0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch new file mode 100644 index 0000000..f79d3ad --- /dev/null +++ b/SOURCES/0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch @@ -0,0 +1,38 @@ +From 90b72b787a6ae6b9b0bf8ece238e108e8607a433 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Sat, 9 Nov 2013 18:13:43 +0100 +Subject: [PATCH 1/2] obex: Use GLib helper function to manipulate paths + +Instead of trying to do it by hand. This also makes sure that +relative paths aren't used by the agent. +--- + obexd/src/manager.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/obexd/src/manager.c b/obexd/src/manager.c +index f84384ae4..285c07c37 100644 +--- a/obexd/src/manager.c ++++ b/obexd/src/manager.c +@@ -650,14 +650,14 @@ static void agent_reply(DBusPendingCall *call, void *user_data) + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) { + /* Splits folder and name */ +- const char *slash = strrchr(name, '/'); ++ gboolean is_relative = !g_path_is_absolute(name); + DBG("Agent replied with %s", name); +- if (!slash) { +- agent->new_name = g_strdup(name); ++ if (is_relative) { ++ agent->new_name = g_path_get_basename(name); + agent->new_folder = NULL; + } else { +- agent->new_name = g_strdup(slash + 1); +- agent->new_folder = g_strndup(name, slash - name); ++ agent->new_name = g_path_get_basename(name); ++ agent->new_folder = g_path_get_dirname(name); + } + } + +-- +2.14.1 + diff --git a/SOURCES/0001-sdpd-Fix-leaking-buffers-stored-in-cstates-cache.patch b/SOURCES/0001-sdpd-Fix-leaking-buffers-stored-in-cstates-cache.patch new file mode 100644 index 0000000..11ce041 --- /dev/null +++ b/SOURCES/0001-sdpd-Fix-leaking-buffers-stored-in-cstates-cache.patch @@ -0,0 +1,468 @@ +From 4e6a2402ed4f46ea026ad0929fbc14faecf3a475 Mon Sep 17 00:00:00 2001 +From: Gopal Tiwari +Date: Wed, 1 Dec 2021 12:18:24 +0530 +Subject: [PATCH BlueZ] sdpd: Fix leaking buffers stored in cstates cache + +commit e79417ed7185b150a056d4eb3a1ab528b91d2fc0 +Author: Luiz Augusto von Dentz +Date: Thu Jul 15 11:01:20 2021 -0700 + + sdpd: Fix leaking buffers stored in cstates cache + + These buffer shall only be keep in cache for as long as they are + needed so this would cleanup any client cstates in the following + conditions: + + - There is no cstate on the response + - No continuation can be found for cstate + - Different request opcode + - Respond with an error + - Client disconnect + + Fixes: https://github.com/bluez/bluez/security/advisories/GHSA-3fqg-r8j5-f5xq +--- + src/sdpd-request.c | 170 ++++++++++++++++++++++++++++++++------------- + src/sdpd-server.c | 20 +++--- + src/sdpd.h | 3 + + unit/test-sdp.c | 2 +- + 4 files changed, 135 insertions(+), 60 deletions(-) + +diff --git a/src/sdpd-request.c b/src/sdpd-request.c +index 033d1e5bf..c8f5a2c72 100644 +--- a/src/sdpd-request.c ++++ b/src/sdpd-request.c +@@ -42,48 +42,78 @@ typedef struct { + + #define MIN(x, y) ((x) < (y)) ? (x): (y) + +-typedef struct _sdp_cstate_list sdp_cstate_list_t; ++typedef struct sdp_cont_info sdp_cont_info_t; + +-struct _sdp_cstate_list { +- sdp_cstate_list_t *next; ++struct sdp_cont_info { ++ int sock; ++ uint8_t opcode; + uint32_t timestamp; + sdp_buf_t buf; + }; + +-static sdp_cstate_list_t *cstates; ++static sdp_list_t *cstates; + +-/* FIXME: should probably remove it when it's found */ +-static sdp_buf_t *sdp_get_cached_rsp(sdp_cont_state_t *cstate) ++static int cstate_match(const void *data, const void *user_data) + { +- sdp_cstate_list_t *p; ++ const sdp_cont_info_t *cinfo = data; ++ const sdp_cont_state_t *cstate = user_data; + +- for (p = cstates; p; p = p->next) { +- /* Check timestamp */ +- if (p->timestamp != cstate->timestamp) +- continue; ++ /* Check timestamp */ ++ return cinfo->timestamp - cstate->timestamp; ++} ++ ++static void sdp_cont_info_free(sdp_cont_info_t *cinfo) ++{ ++ if (!cinfo) ++ return; ++ ++ cstates = sdp_list_remove(cstates, cinfo); ++ free(cinfo->buf.data); ++ free(cinfo); ++} ++ ++static sdp_cont_info_t *sdp_get_cont_info(sdp_req_t *req, ++ sdp_cont_state_t *cstate) ++{ ++ sdp_list_t *list; ++ ++ list = sdp_list_find(cstates, cstate, cstate_match); ++ if (list) { ++ sdp_cont_info_t *cinfo = list->data; + +- /* Check if requesting more than available */ +- if (cstate->cStateValue.maxBytesSent < p->buf.data_size) +- return &p->buf; ++ if (cinfo->opcode == req->opcode) ++ return cinfo; ++ ++ /* Cleanup continuation if the opcode doesn't match since its ++ * response buffer shall only be valid for the original requests ++ */ ++ sdp_cont_info_free(cinfo); ++ return NULL; + } + +- return 0; ++ /* Cleanup cstates if no continuation info could be found */ ++ sdp_cstate_cleanup(req->sock); ++ ++ return NULL; + } + +-static uint32_t sdp_cstate_alloc_buf(sdp_buf_t *buf) ++static uint32_t sdp_cstate_alloc_buf(sdp_req_t *req, sdp_buf_t *buf) + { +- sdp_cstate_list_t *cstate = malloc(sizeof(sdp_cstate_list_t)); ++ sdp_cont_info_t *cinfo = malloc(sizeof(sdp_cont_info_t)); + uint8_t *data = malloc(buf->data_size); + + memcpy(data, buf->data, buf->data_size); +- memset((char *)cstate, 0, sizeof(sdp_cstate_list_t)); +- cstate->buf.data = data; +- cstate->buf.data_size = buf->data_size; +- cstate->buf.buf_size = buf->data_size; +- cstate->timestamp = sdp_get_time(); +- cstate->next = cstates; +- cstates = cstate; +- return cstate->timestamp; ++ memset(cinfo, 0, sizeof(sdp_cont_info_t)); ++ cinfo->buf.data = data; ++ cinfo->buf.data_size = buf->data_size; ++ cinfo->buf.buf_size = buf->data_size; ++ cinfo->timestamp = sdp_get_time(); ++ cinfo->sock = req->sock; ++ cinfo->opcode = req->opcode; ++ ++ cstates = sdp_list_append(cstates, cinfo); ++ ++ return cinfo->timestamp; + } + + /* Additional values for checking datatype (not in spec) */ +@@ -274,14 +304,16 @@ static int sdp_set_cstate_pdu(sdp_buf_t *buf, sdp_cont_state_t *cstate) + return length; + } + +-static int sdp_cstate_get(uint8_t *buffer, size_t len, +- sdp_cont_state_t **cstate) ++static int sdp_cstate_get(sdp_req_t *req, uint8_t *buffer, size_t len, ++ sdp_cont_state_t **cstate, sdp_cont_info_t **cinfo) + { + uint8_t cStateSize = *buffer; + + SDPDBG("Continuation State size : %d", cStateSize); + + if (cStateSize == 0) { ++ /* Cleanup cstates if request doesn't contain a cstate */ ++ sdp_cstate_cleanup(req->sock); + *cstate = NULL; + return 0; + } +@@ -306,6 +338,8 @@ static int sdp_cstate_get(uint8_t *buffer, size_t len, + SDPDBG("Cstate TS : 0x%x", (*cstate)->timestamp); + SDPDBG("Bytes sent : %d", (*cstate)->cStateValue.maxBytesSent); + ++ *cinfo = sdp_get_cont_info(req, *cstate); ++ + return 0; + } + +@@ -360,6 +394,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + uint16_t expected, actual, rsp_count = 0; + uint8_t dtd; + sdp_cont_state_t *cstate = NULL; ++ sdp_cont_info_t *cinfo = NULL; + uint8_t *pCacheBuffer = NULL; + int handleSize = 0; + uint32_t cStateId = 0; +@@ -399,9 +434,9 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + + /* + * Check if continuation state exists, if yes attempt +- * to get rsp remainder from cache, else send error ++ * to get rsp remainder from continuation info, else send error + */ +- if (sdp_cstate_get(pdata, data_left, &cstate) < 0) { ++ if (sdp_cstate_get(req, pdata, data_left, &cstate, &cinfo) < 0) { + status = SDP_INVALID_SYNTAX; + goto done; + } +@@ -451,7 +486,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + + if (rsp_count > actual) { + /* cache the rsp and generate a continuation state */ +- cStateId = sdp_cstate_alloc_buf(buf); ++ cStateId = sdp_cstate_alloc_buf(req, buf); + /* + * subtract handleSize since we now send only + * a subset of handles +@@ -459,6 +494,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + buf->data_size -= handleSize; + } else { + /* NULL continuation state */ ++ sdp_cont_info_free(cinfo); + sdp_set_cstate_pdu(buf, NULL); + } + } +@@ -468,13 +504,15 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + short lastIndex = 0; + + if (cstate) { +- /* +- * Get the previous sdp_cont_state_t and obtain +- * the cached rsp +- */ +- sdp_buf_t *pCache = sdp_get_cached_rsp(cstate); +- if (pCache) { +- pCacheBuffer = pCache->data; ++ if (cinfo) { ++ /* Check if requesting more than available */ ++ if (cstate->cStateValue.maxBytesSent >= ++ cinfo->buf.data_size) { ++ status = SDP_INVALID_CSTATE; ++ goto done; ++ } ++ ++ pCacheBuffer = cinfo->buf.data; + /* get the rsp_count from the cached buffer */ + rsp_count = get_be16(pCacheBuffer); + +@@ -518,6 +556,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + if (i == rsp_count) { + /* set "null" continuationState */ + sdp_set_cstate_pdu(buf, NULL); ++ sdp_cont_info_free(cinfo); + } else { + /* + * there's more: set lastIndexSent to +@@ -540,6 +579,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) + + done: + free(cstate); ++ + if (pattern) + sdp_list_free(pattern, free); + +@@ -619,15 +659,21 @@ static int extract_attrs(sdp_record_t *rec, sdp_list_t *seq, sdp_buf_t *buf) + } + + /* Build cstate response */ +-static int sdp_cstate_rsp(sdp_cont_state_t *cstate, sdp_buf_t *buf, +- uint16_t max) ++static int sdp_cstate_rsp(sdp_cont_info_t *cinfo, sdp_cont_state_t *cstate, ++ sdp_buf_t *buf, uint16_t max) + { +- /* continuation State exists -> get from cache */ +- sdp_buf_t *cache = sdp_get_cached_rsp(cstate); ++ sdp_buf_t *cache; + uint16_t sent; + +- if (!cache) ++ if (!cinfo) ++ return 0; ++ ++ if (cstate->cStateValue.maxBytesSent >= cinfo->buf.data_size) { ++ sdp_cont_info_free(cinfo); + return 0; ++ } ++ ++ cache = &cinfo->buf; + + sent = MIN(max, cache->data_size - cstate->cStateValue.maxBytesSent); + memcpy(buf->data, cache->data + cstate->cStateValue.maxBytesSent, sent); +@@ -637,8 +683,10 @@ static int sdp_cstate_rsp(sdp_cont_state_t *cstate, sdp_buf_t *buf, + SDPDBG("Response size : %d sending now : %d bytes sent so far : %d", + cache->data_size, sent, cstate->cStateValue.maxBytesSent); + +- if (cstate->cStateValue.maxBytesSent == cache->data_size) ++ if (cstate->cStateValue.maxBytesSent == cache->data_size) { ++ sdp_cont_info_free(cinfo); + return sdp_set_cstate_pdu(buf, NULL); ++ } + + return sdp_set_cstate_pdu(buf, cstate); + } +@@ -652,6 +700,7 @@ static int sdp_cstate_rsp(sdp_cont_state_t *cstate, sdp_buf_t *buf, + static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf) + { + sdp_cont_state_t *cstate = NULL; ++ sdp_cont_info_t *cinfo = NULL; + short cstate_size = 0; + sdp_list_t *seq = NULL; + uint8_t dtd = 0; +@@ -708,7 +757,7 @@ static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf) + * if continuation state exists, attempt + * to get rsp remainder from cache, else send error + */ +- if (sdp_cstate_get(pdata, data_left, &cstate) < 0) { ++ if (sdp_cstate_get(req, pdata, data_left, &cstate, &cinfo) < 0) { + status = SDP_INVALID_SYNTAX; + goto done; + } +@@ -737,7 +786,7 @@ static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf) + buf->buf_size -= sizeof(uint16_t); + + if (cstate) { +- cstate_size = sdp_cstate_rsp(cstate, buf, max_rsp_size); ++ cstate_size = sdp_cstate_rsp(cinfo, cstate, buf, max_rsp_size); + if (!cstate_size) { + status = SDP_INVALID_CSTATE; + error("NULL cache buffer and non-NULL continuation state"); +@@ -749,7 +798,7 @@ static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf) + sdp_cont_state_t newState; + + memset((char *)&newState, 0, sizeof(sdp_cont_state_t)); +- newState.timestamp = sdp_cstate_alloc_buf(buf); ++ newState.timestamp = sdp_cstate_alloc_buf(req, buf); + /* + * Reset the buffer size to the maximum expected and + * set the sdp_cont_state_t +@@ -793,6 +842,7 @@ static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf) + int scanned, rsp_count = 0; + sdp_list_t *pattern = NULL, *seq = NULL, *svcList; + sdp_cont_state_t *cstate = NULL; ++ sdp_cont_info_t *cinfo = NULL; + short cstate_size = 0; + uint8_t dtd = 0; + sdp_buf_t tmpbuf; +@@ -852,7 +902,7 @@ static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf) + * if continuation state exists attempt + * to get rsp remainder from cache, else send error + */ +- if (sdp_cstate_get(pdata, data_left, &cstate) < 0) { ++ if (sdp_cstate_get(req, pdata, data_left, &cstate, &cinfo) < 0) { + status = SDP_INVALID_SYNTAX; + goto done; + } +@@ -906,7 +956,7 @@ static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf) + sdp_cont_state_t newState; + + memset((char *)&newState, 0, sizeof(sdp_cont_state_t)); +- newState.timestamp = sdp_cstate_alloc_buf(buf); ++ newState.timestamp = sdp_cstate_alloc_buf(req, buf); + /* + * Reset the buffer size to the maximum expected and + * set the sdp_cont_state_t +@@ -917,7 +967,7 @@ static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf) + } else + cstate_size = sdp_set_cstate_pdu(buf, NULL); + } else { +- cstate_size = sdp_cstate_rsp(cstate, buf, max); ++ cstate_size = sdp_cstate_rsp(cinfo, cstate, buf, max); + if (!cstate_size) { + status = SDP_INVALID_CSTATE; + SDPDBG("Non-null continuation state, but null cache buffer"); +@@ -974,6 +1024,9 @@ static void process_request(sdp_req_t *req) + status = SDP_INVALID_PDU_SIZE; + goto send_rsp; + } ++ ++ req->opcode = reqhdr->pdu_id; ++ + switch (reqhdr->pdu_id) { + case SDP_SVC_SEARCH_REQ: + SDPDBG("Got a svc srch req"); +@@ -1020,6 +1073,8 @@ static void process_request(sdp_req_t *req) + + send_rsp: + if (status) { ++ /* Cleanup cstates on error */ ++ sdp_cstate_cleanup(req->sock); + rsphdr->pdu_id = SDP_ERROR_RSP; + put_be16(status, rsp.data); + rsp.data_size = sizeof(uint16_t); +@@ -1108,3 +1163,20 @@ void handle_request(int sk, uint8_t *data, int len) + + process_request(&req); + } ++ ++void sdp_cstate_cleanup(int sock) ++{ ++ sdp_list_t *list; ++ ++ /* Remove any cinfo for the client */ ++ for (list = cstates; list;) { ++ sdp_cont_info_t *cinfo = list->data; ++ ++ list = list->next; ++ ++ if (cinfo->sock != sock) ++ continue; ++ ++ sdp_cont_info_free(cinfo); ++ } ++} +diff --git a/src/sdpd-server.c b/src/sdpd-server.c +index dfd8b1f00..66ee7ba14 100644 +--- a/src/sdpd-server.c ++++ b/src/sdpd-server.c +@@ -146,16 +146,12 @@ static gboolean io_session_event(GIOChannel *chan, GIOCondition cond, gpointer d + + sk = g_io_channel_unix_get_fd(chan); + +- if (cond & (G_IO_HUP | G_IO_ERR)) { +- sdp_svcdb_collect_all(sk); +- return FALSE; +- } ++ if (cond & (G_IO_HUP | G_IO_ERR)) ++ goto cleanup; + + len = recv(sk, &hdr, sizeof(sdp_pdu_hdr_t), MSG_PEEK); +- if (len < 0 || (unsigned int) len < sizeof(sdp_pdu_hdr_t)) { +- sdp_svcdb_collect_all(sk); +- return FALSE; +- } ++ if (len < 0 || (unsigned int) len < sizeof(sdp_pdu_hdr_t)) ++ goto cleanup; + + size = sizeof(sdp_pdu_hdr_t) + ntohs(hdr.plen); + buf = malloc(size); +@@ -168,14 +164,18 @@ static gboolean io_session_event(GIOChannel *chan, GIOCondition cond, gpointer d + * inside handle_request() in order to produce ErrorResponse. + */ + if (len <= 0) { +- sdp_svcdb_collect_all(sk); + free(buf); +- return FALSE; ++ goto cleanup; + } + + handle_request(sk, buf, len); + + return TRUE; ++ ++cleanup: ++ sdp_svcdb_collect_all(sk); ++ sdp_cstate_cleanup(sk); ++ return FALSE; + } + + static gboolean io_accept_event(GIOChannel *chan, GIOCondition cond, gpointer data) +diff --git a/src/sdpd.h b/src/sdpd.h +index 257411f03..4316aff67 100644 +--- a/src/sdpd.h ++++ b/src/sdpd.h +@@ -27,8 +27,11 @@ typedef struct request { + int flags; + uint8_t *buf; + int len; ++ uint8_t opcode; + } sdp_req_t; + ++void sdp_cstate_cleanup(int sock); ++ + void handle_internal_request(int sk, int mtu, void *data, int len); + void handle_request(int sk, uint8_t *data, int len); + +diff --git a/unit/test-sdp.c b/unit/test-sdp.c +index d3a885f19..8f95fcb71 100644 +--- a/unit/test-sdp.c ++++ b/unit/test-sdp.c +@@ -235,7 +235,7 @@ static gboolean client_handler(GIOChannel *channel, GIOCondition cond, + tester_monitor('>', 0x0000, 0x0001, buf, len); + + g_assert(len > 0); +- g_assert((size_t) len == rsp_pdu->raw_size + rsp_pdu->cont_len); ++ g_assert_cmpuint(len, ==, rsp_pdu->raw_size + rsp_pdu->cont_len); + + g_assert(memcmp(buf, rsp_pdu->raw_data, rsp_pdu->raw_size) == 0); + +-- +2.26.2 + diff --git a/SOURCES/69-btattach-bcm.rules b/SOURCES/69-btattach-bcm.rules new file mode 100644 index 0000000..dfe8d1e --- /dev/null +++ b/SOURCES/69-btattach-bcm.rules @@ -0,0 +1,33 @@ +# Some devices have a bluetooth HCI connected to an uart, these needs to be +# setup by calling btattach. The systemd btattach-bcm.service takes care of +# this. These udev rules hardware-activate that service when necessary. +# +# For now this only suports ACPI enumerated Broadcom BT HCIs. +# This has been tested on Bay and Cherry Trail devices with both ACPI and +# PCI enumerated UARTs. + +# Note we check for the platform device not for the acpi device, because +# some DSDTs list multiple bluetooth adapters, but only some (or none) +# are enabled. Only enabled adapters get a platform device created. +ACTION!="add", GOTO="btattach_bcm_rules_end" +SUBSYSTEM!="platform", GOTO="btattach_bcm_rules_end" + +KERNEL=="BCM2E1A:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E39:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E3A:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E3D:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E3F:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E40:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E54:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E55:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E64:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E65:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E67:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E71:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E7B:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E7C:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E7E:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E95:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" +KERNEL=="BCM2E96:00", TAG+="systemd", ENV{SYSTEMD_WANTS}="btattach-bcm@%k.service" + +LABEL="btattach_bcm_rules_end" diff --git a/SOURCES/bluez.gitignore b/SOURCES/bluez.gitignore new file mode 100644 index 0000000..137d2e5 --- /dev/null +++ b/SOURCES/bluez.gitignore @@ -0,0 +1,100 @@ +*.o +*.a +*.lo +*.la +*.so +.deps +.libs +.dirstamp +Makefile +Makefile.in +aclocal.m4 +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +depcomp +compile +install-sh +libtool +ltmain.sh +missing +stamp-h1 +autom4te.cache + +ylwrap +lexer.c +parser.h +parser.c + +bluez.pc +lib/bluetooth +src/builtin.h +src/bluetoothd +audio/telephony.c +sap/sap.c +scripts/bluetooth.rules +scripts/97-bluetooth.rules +scripts/97-bluetooth-hid2hci.rules + +sbc/sbcdec +sbc/sbcenc +sbc/sbcinfo +sbc/sbctester + +attrib/gatttool +tools/avctrl +tools/avinfo +tools/bccmd +tools/ciptool +tools/dfubabel +tools/dfutool +tools/hciattach +tools/hciconfig +tools/hcieventmask +tools/hcisecfilter +tools/hcitool +tools/hid2hci +tools/rfcomm +tools/l2ping +tools/ppporc +tools/sdptool +cups/bluetooth +test/agent +test/bdaddr +test/hciemu +test/attest +test/hstest +test/avtest +test/l2test +test/rctest +test/scotest +test/gaptest +test/sdptest +test/lmptest +test/ipctest +test/btiotest +test/test-textfile +test/uuidtest +test/mpris-player +compat/dund +compat/hidd +compat/pand +unit/test-eir +mgmt/btmgmt +monitor/btmon +emulator/btvirt + +doc/*.bak +doc/*.stamp +doc/bluez.* +doc/bluez-*.txt +doc/*.sgml +doc/version.xml +doc/xml +doc/html +src/bluetoothd.8 +src/bluetooth.service diff --git a/SOURCES/btattach-bcm-service.sh b/SOURCES/btattach-bcm-service.sh new file mode 100644 index 0000000..c7f8b17 --- /dev/null +++ b/SOURCES/btattach-bcm-service.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Simple shell script to wait for the tty for an uart using BT HCI to show up +# and then invoke btattach with the right parameters, this is intended to be +# invoked from a hardware-activated systemd service +# +# For now this only suports ACPI enumerated Broadcom BT HCIs. +# This has been tested on Bay and Cherry Trail devices with both ACPI and +# PCI enumerated UARTs. +# +# Note the kernel bt developers are working on solving this entirely in the +# kernel, so it is not worth the trouble to write something better then this. + +BT_DEV="/sys/bus/platform/devices/$1" +BT_DEV="$(readlink -f $BT_DEV)" +UART_DEV="$(dirname $BT_DEV)" + +# Stupid GPD-pocket has USB BT with id 0000:0000, but still claims to have +# an uart attached bt +if [ "$1" = "BCM2E7E:00" ] && lsusb | grep -q "ID 0000:0000"; then + exit 0 +fi + +while [ ! -d "$UART_DEV/tty" ]; do + sleep .2 +done + +TTY="$(ls $UART_DEV/tty)" + +exec btattach --bredr "/dev/$TTY" -P bcm diff --git a/SOURCES/btattach-bcm@.service b/SOURCES/btattach-bcm@.service new file mode 100644 index 0000000..1e7c7db --- /dev/null +++ b/SOURCES/btattach-bcm@.service @@ -0,0 +1,6 @@ +[Unit] +Description=btattach for Broadcom devices + +[Service] +Type=simple +ExecStart=/usr/libexec/bluetooth/btattach-bcm-service.sh %I diff --git a/SPECS/bluez.spec b/SPECS/bluez.spec index 6473e9b..49a9776 100644 --- a/SPECS/bluez.spec +++ b/SPECS/bluez.spec @@ -1,7 +1,7 @@ Name: bluez Summary: Bluetooth utilities Version: 5.56 -Release: 2%{?dist} +Release: 3%{?dist} License: GPLv2+ URL: http://www.bluez.org/ @@ -46,6 +46,8 @@ Patch24: 0001-adapter-Don-t-refresh-adv_manager-for-non-LE-devices.patch # fixing https://bugzilla.redhat.com/show_bug.cgi?id=1965057 Patch31: 0001-shared-gatt-server-Fix-not-properly-checking-for-sec.patch +Patch32: 0001-sdpd-Fix-leaking-buffers-stored-in-cstates-cache.patch + BuildRequires: git-core BuildRequires: dbus-devel >= 1.6 BuildRequires: glib2-devel @@ -279,6 +281,11 @@ make check %changelog +* Wed Dec 13 2021 Gopal Tiwari - 5.56-3 ++ bluez-5.56-3 +- Fixing (#2027434) +- Fixing CVE-2021-41229 + * Mon Jun 7 2021 Gopal Tiwari - 5.56-2 + bluez-5.56-2 - Fixing (#1968392)