Toshaan Bharvani
3 years ago
commit
5834ac94b4
10 changed files with 2047 additions and 0 deletions
@ -0,0 +1,35 @@ |
|||||||
|
From 5744f79d84ecee3929a682166034c5bbc36c0ef5 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Bastien Nocera <hadess@hadess.net> |
||||||
|
Date: Wed, 20 Sep 2017 12:49:10 +0200 |
||||||
|
Subject: [PATCH 1/4] build: Always define confdir and statedir |
||||||
|
|
||||||
|
As we will need those paths to lock down on them. |
||||||
|
--- |
||||||
|
Makefile.am | 6 +++--- |
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-) |
||||||
|
|
||||||
|
diff --git a/Makefile.am b/Makefile.am |
||||||
|
index 9d25a815b..ac88c12e0 100644 |
||||||
|
--- a/Makefile.am |
||||||
|
+++ b/Makefile.am |
||||||
|
@@ -31,14 +31,14 @@ pkginclude_HEADERS = |
||||||
|
AM_CFLAGS = $(WARNING_CFLAGS) $(MISC_CFLAGS) $(UDEV_CFLAGS) $(ell_cflags) |
||||||
|
AM_LDFLAGS = $(MISC_LDFLAGS) |
||||||
|
|
||||||
|
+confdir = $(sysconfdir)/bluetooth |
||||||
|
+statedir = $(localstatedir)/lib/bluetooth |
||||||
|
+ |
||||||
|
if DATAFILES |
||||||
|
dbusdir = $(DBUS_CONFDIR)/dbus-1/system.d |
||||||
|
dbus_DATA = src/bluetooth.conf |
||||||
|
|
||||||
|
-confdir = $(sysconfdir)/bluetooth |
||||||
|
conf_DATA = |
||||||
|
- |
||||||
|
-statedir = $(localstatedir)/lib/bluetooth |
||||||
|
state_DATA = |
||||||
|
endif |
||||||
|
|
||||||
|
-- |
||||||
|
2.21.0 |
||||||
|
|
@ -0,0 +1,38 @@ |
|||||||
|
From 90b72b787a6ae6b9b0bf8ece238e108e8607a433 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Bastien Nocera <hadess@hadess.net> |
||||||
|
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 |
||||||
|
|
@ -0,0 +1,468 @@ |
|||||||
|
From 4e6a2402ed4f46ea026ad0929fbc14faecf3a475 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Gopal Tiwari <gtiwari@redhat.com> |
||||||
|
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 <luiz.von.dentz@intel.com> |
||||||
|
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 |
||||||
|
|
@ -0,0 +1,38 @@ |
|||||||
|
From 36a44fc05feebe1aab16c33a1121f952986b2801 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Craig Andrews <candrews@integralblue.com> |
||||||
|
Date: Wed, 13 Sep 2017 15:23:09 +0200 |
||||||
|
Subject: [PATCH 2/4] systemd: Add PrivateTmp and NoNewPrivileges options |
||||||
|
|
||||||
|
PrivateTmp makes bluetoothd's /tmp and /var/tmp be inside a different |
||||||
|
namespace. This is useful to secure access to temporary files of the |
||||||
|
process. |
||||||
|
|
||||||
|
NoNewPrivileges ensures that service process and all its children |
||||||
|
can never gain new privileges through execve(), lowering the risk of |
||||||
|
possible privilege escalations. |
||||||
|
--- |
||||||
|
src/bluetooth.service.in | 6 ++++++ |
||||||
|
1 file changed, 6 insertions(+) |
||||||
|
|
||||||
|
diff --git a/src/bluetooth.service.in b/src/bluetooth.service.in |
||||||
|
index f9faaa452..7c2f60bb4 100644 |
||||||
|
--- a/src/bluetooth.service.in |
||||||
|
+++ b/src/bluetooth.service.in |
||||||
|
@@ -12,8 +12,14 @@ NotifyAccess=main |
||||||
|
#Restart=on-failure |
||||||
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE |
||||||
|
LimitNPROC=1 |
||||||
|
+ |
||||||
|
+# Filesystem lockdown |
||||||
|
ProtectHome=true |
||||||
|
ProtectSystem=full |
||||||
|
+PrivateTmp=true |
||||||
|
+ |
||||||
|
+# Privilege escalation |
||||||
|
+NoNewPrivileges=true |
||||||
|
|
||||||
|
[Install] |
||||||
|
WantedBy=bluetooth.target |
||||||
|
-- |
||||||
|
2.21.0 |
||||||
|
|
@ -0,0 +1,44 @@ |
|||||||
|
From 13a348670fef0047555395ce6977e86e0005f8bd Mon Sep 17 00:00:00 2001 |
||||||
|
From: Bastien Nocera <hadess@hadess.net> |
||||||
|
Date: Wed, 13 Sep 2017 15:37:11 +0200 |
||||||
|
Subject: [PATCH 3/4] systemd: Add more filesystem lockdown |
||||||
|
|
||||||
|
We can only access the configuration file as read-only and read-write |
||||||
|
to the Bluetooth cache directory and sub-directories. |
||||||
|
--- |
||||||
|
Makefile.am | 3 +++ |
||||||
|
src/bluetooth.service.in | 4 ++++ |
||||||
|
2 files changed, 7 insertions(+) |
||||||
|
|
||||||
|
diff --git a/Makefile.am b/Makefile.am |
||||||
|
index ac88c12e0..0a6d09847 100644 |
||||||
|
--- a/Makefile.am |
||||||
|
+++ b/Makefile.am |
||||||
|
@@ -562,6 +562,9 @@ MAINTAINERCLEANFILES = Makefile.in \ |
||||||
|
|
||||||
|
SED_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ |
||||||
|
$(SED) -e 's,@pkglibexecdir\@,$(pkglibexecdir),g' \ |
||||||
|
+ -e 's,@libexecdir\@,$(libexecdir),g' \ |
||||||
|
+ -e 's,@statedir\@,$(statedir),g' \ |
||||||
|
+ -e 's,@confdir\@,$(confdir),g' \ |
||||||
|
< $< > $@ |
||||||
|
|
||||||
|
%.service: %.service.in Makefile |
||||||
|
diff --git a/src/bluetooth.service.in b/src/bluetooth.service.in |
||||||
|
index 7c2f60bb4..4daedef2a 100644 |
||||||
|
--- a/src/bluetooth.service.in |
||||||
|
+++ b/src/bluetooth.service.in |
||||||
|
@@ -17,6 +17,10 @@ LimitNPROC=1 |
||||||
|
ProtectHome=true |
||||||
|
ProtectSystem=full |
||||||
|
PrivateTmp=true |
||||||
|
+ProtectKernelTunables=true |
||||||
|
+ProtectControlGroups=true |
||||||
|
+ReadWritePaths=@statedir@ |
||||||
|
+ReadOnlyPaths=@confdir@ |
||||||
|
|
||||||
|
# Privilege escalation |
||||||
|
NoNewPrivileges=true |
||||||
|
-- |
||||||
|
2.21.0 |
||||||
|
|
@ -0,0 +1,34 @@ |
|||||||
|
From a6963e0402695d7b6a89c1b1c75c40dbd8fcde52 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Bastien Nocera <hadess@hadess.net> |
||||||
|
Date: Wed, 13 Sep 2017 15:38:26 +0200 |
||||||
|
Subject: [PATCH 4/4] systemd: More lockdown |
||||||
|
|
||||||
|
bluetoothd does not need to execute mapped memory, or real-time |
||||||
|
access, so block those. |
||||||
|
--- |
||||||
|
src/bluetooth.service.in | 6 ++++++ |
||||||
|
1 file changed, 6 insertions(+) |
||||||
|
|
||||||
|
diff --git a/src/bluetooth.service.in b/src/bluetooth.service.in |
||||||
|
index 4daedef2a..f18801866 100644 |
||||||
|
--- a/src/bluetooth.service.in |
||||||
|
+++ b/src/bluetooth.service.in |
||||||
|
@@ -22,9 +22,15 @@ ProtectControlGroups=true |
||||||
|
ReadWritePaths=@statedir@ |
||||||
|
ReadOnlyPaths=@confdir@ |
||||||
|
|
||||||
|
+# Execute Mappings |
||||||
|
+MemoryDenyWriteExecute=true |
||||||
|
+ |
||||||
|
# Privilege escalation |
||||||
|
NoNewPrivileges=true |
||||||
|
|
||||||
|
+# Real-time |
||||||
|
+RestrictRealtime=true |
||||||
|
+ |
||||||
|
[Install] |
||||||
|
WantedBy=bluetooth.target |
||||||
|
Alias=dbus-org.bluez.service |
||||||
|
-- |
||||||
|
2.21.0 |
||||||
|
|
@ -0,0 +1,42 @@ |
|||||||
|
From 124dee151746b4a8a2e8a7194af78f2c82f75d79 Mon Sep 17 00:00:00 2001 |
||||||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> |
||||||
|
Date: Wed, 3 Mar 2021 08:57:36 +0100 |
||||||
|
Subject: [PATCH] media: rename local function conflicting with pause(2) |
||||||
|
|
||||||
|
profiles/audio/media.c:1284:13: error: conflicting types for 'pause'; have '_Bool(void *)' |
||||||
|
1284 | static bool pause(void *user_data) |
||||||
|
| ^~~~~ |
||||||
|
In file included from /usr/include/bits/sigstksz.h:24, |
||||||
|
from /usr/include/signal.h:315, |
||||||
|
from /usr/include/glib-2.0/glib/gbacktrace.h:36, |
||||||
|
from /usr/include/glib-2.0/glib.h:34, |
||||||
|
from profiles/audio/media.c:21: |
||||||
|
/usr/include/unistd.h:478:12: note: previous declaration of 'pause' with type 'int(void)' |
||||||
|
478 | extern int pause (void); |
||||||
|
| ^~~~~ |
||||||
|
--- |
||||||
|
profiles/audio/media.c | 4 ++-- |
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-) |
||||||
|
|
||||||
|
diff --git a/profiles/audio/media.c b/profiles/audio/media.c |
||||||
|
index c84bbe22dc..3d8c4b69c3 100644 |
||||||
|
--- a/profiles/audio/media.c |
||||||
|
+++ b/profiles/audio/media.c |
||||||
|
@@ -1281,7 +1281,7 @@ static bool stop(void *user_data) |
||||||
|
return media_player_send(mp, "Stop"); |
||||||
|
} |
||||||
|
|
||||||
|
-static bool pause(void *user_data) |
||||||
|
+static bool pause_play(void *user_data) |
||||||
|
{ |
||||||
|
struct media_player *mp = user_data; |
||||||
|
|
||||||
|
@@ -1331,7 +1331,7 @@ static struct avrcp_player_cb player_cb = { |
||||||
|
.set_volume = set_volume, |
||||||
|
.play = play, |
||||||
|
.stop = stop, |
||||||
|
- .pause = pause, |
||||||
|
+ .pause = pause_play, |
||||||
|
.next = next, |
||||||
|
.previous = previous, |
||||||
|
}; |
@ -0,0 +1,41 @@ |
|||||||
|
From 28ddec8d6b829e002fa268c07b71e4c564ba9e16 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
||||||
|
Date: Thu, 11 Mar 2021 07:36:07 -0800 |
||||||
|
Subject: [PATCH] avdtp: Fix removing all remote SEPs when loading from cache |
||||||
|
|
||||||
|
If avdtp_discover is called after cache has been loaded it end up |
||||||
|
removing all remote SEPs as they have not been discovered yet. |
||||||
|
|
||||||
|
Fixes: https://github.com/bluez/bluez/issues/102 |
||||||
|
--- |
||||||
|
profiles/audio/avdtp.c | 16 ++++++++++++---- |
||||||
|
1 file changed, 12 insertions(+), 4 deletions(-) |
||||||
|
|
||||||
|
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c |
||||||
|
index 088ca58b3..1d5871c62 100644 |
||||||
|
--- a/profiles/audio/avdtp.c |
||||||
|
+++ b/profiles/audio/avdtp.c |
||||||
|
@@ -3381,10 +3381,18 @@ int avdtp_discover(struct avdtp *session, avdtp_discover_cb_t cb, |
||||||
|
session->discover = g_new0(struct discover_callback, 1); |
||||||
|
|
||||||
|
if (session->seps) { |
||||||
|
- session->discover->cb = cb; |
||||||
|
- session->discover->user_data = user_data; |
||||||
|
- session->discover->id = g_idle_add(process_discover, session); |
||||||
|
- return 0; |
||||||
|
+ struct avdtp_remote_sep *sep = session->seps->data; |
||||||
|
+ |
||||||
|
+ /* Check that SEP have been discovered as it may be loaded from |
||||||
|
+ * cache. |
||||||
|
+ */ |
||||||
|
+ if (sep->discovered) { |
||||||
|
+ session->discover->cb = cb; |
||||||
|
+ session->discover->user_data = user_data; |
||||||
|
+ session->discover->id = g_idle_add(process_discover, |
||||||
|
+ session); |
||||||
|
+ return 0; |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
err = send_request(session, FALSE, NULL, AVDTP_DISCOVER, NULL, 0); |
||||||
|
|
@ -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 |
Loading…
Reference in new issue