From: Bastien Nocera <hadess@hadess.net>
To: linux-bluetooth@vger.kernel.org
Subject: [BlueZ, v3 2/9] sdp-xml: Fix crash caused by type confusion when parsing crafted SDP XML
Date: Tue, 11 Aug 2026 16:54:05 +0200 [thread overview]
Message-ID: <20260811145704.1766949-3-hadess@hadess.net> (raw)
In-Reply-To: <20260811145704.1766949-1-hadess@hadess.net>
When element_end() processes </attribute>, it frees ctx_data->stack_head
and clears the stack even if parsing is still nested inside a parent
container.
If a crafted ServiceRecord places a nested <attribute> inside <sequence>,
a later sibling scalar element such as <uint64> can become the new stack
head. When the closing </sequence> is then processed, compute_seq_size()
is reached without first validating that the current node is actually
a sequence.
sdp_data_t.val stores both scalar members such as uint64 and the
dataseq pointer in the same union. As a result, attacker-controlled
scalar data can be reinterpreted as a linked-list pointer and traversed
until bluetoothd crashes.
See https://github.com/bluez/bluez/security/advisories/GHSA-7mmr-gwqx-vc34
Reported-by: Aisle Research
Co-authored-by: Aisle Research
---
src/sdp-xml.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/src/sdp-xml.c b/src/sdp-xml.c
index e5b30e88505f..c8f9ed013b29 100644
--- a/src/sdp-xml.c
+++ b/src/sdp-xml.c
@@ -529,7 +529,9 @@ static void element_end(GMarkupParseContext *context,
return;
if (!strcmp(element_name, "attribute")) {
- if (ctx_data->stack_head && ctx_data->stack_head->data) {
+ /* Attributes are expected at top-level record scope. */
+ if (ctx_data->stack_head && ctx_data->stack_head->data &&
+ ctx_data->stack_head->next == NULL) {
int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id,
ctx_data->stack_head->data);
if (ret == -1)
@@ -539,6 +541,11 @@ static void element_end(GMarkupParseContext *context,
ctx_data->stack_head->data = NULL;
sdp_xml_data_free(ctx_data->stack_head);
ctx_data->stack_head = NULL;
+ } else if (ctx_data->stack_head && ctx_data->stack_head->next) {
+ g_set_error(err, G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Nested <attribute> is invalid");
+ return;
} else {
DBG("No data for attribute 0x%04x", ctx_data->attr_id);
}
@@ -558,6 +565,13 @@ static void element_end(GMarkupParseContext *context,
}
if (!strcmp(element_name, "sequence")) {
+ if (!SDP_IS_SEQ(ctx_data->stack_head->data->dtd)) {
+ g_set_error(err, G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Mismatched </sequence> close");
+ return;
+ }
+
ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
@@ -570,6 +584,13 @@ static void element_end(GMarkupParseContext *context,
ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
}
} else if (!strcmp(element_name, "alternate")) {
+ if (!SDP_IS_ALT(ctx_data->stack_head->data->dtd)) {
+ g_set_error(err, G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Mismatched </alternate> close");
+ return;
+ }
+
ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
--
2.55.0
next prev parent reply other threads:[~2026-08-11 15:10 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 14:54 [BlueZ, v3 0/9] 3 SDP XML security fixes Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 1/9] unit: Add test for sdp_xml_parse_record() Bastien Nocera
2026-08-11 16:33 ` 3 SDP XML security fixes bluez.test.bot
2026-08-11 14:54 ` Bastien Nocera [this message]
2026-08-11 14:54 ` [BlueZ, v3 3/9] unit: Add test for sdp-xml type-confusion bug Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 4/9] sdp-xml: Fix memory leak when adding duplicate attributes Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 5/9] unit: Add test for sdp-xml duplicate attribute bug Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 6/9] sdp-xml: Optimise parsing large sequences Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 7/9] unit: Add test for slow element_end() append Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 8/9] sdp-xml: Fix stack overflow when converting large sequences to XML Bastien Nocera
2026-08-11 14:54 ` [BlueZ, v3 9/9] unit: Add convert_sdp_record_to_xml() to SDP XML testing Bastien Nocera
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260811145704.1766949-3-hadess@hadess.net \
--to=hadess@hadess.net \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.