From: Bastien Nocera <hadess@hadess.net>
To: linux-bluetooth@vger.kernel.org
Subject: [BlueZ, v4 2/9] sdp-xml: Fix crash caused by type confusion when parsing crafted SDP XML
Date: Wed, 12 Aug 2026 10:01:33 +0200 [thread overview]
Message-ID: <20260812080410.2116906-3-hadess@hadess.net> (raw)
In-Reply-To: <20260812080410.2116906-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-12 8:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 8:01 [BlueZ, v4 0/9] 3 SDP XML security fixes Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 1/9] unit: Add test for sdp_xml_parse_record() Bastien Nocera
2026-08-12 9:45 ` 3 SDP XML security fixes bluez.test.bot
2026-08-12 8:01 ` Bastien Nocera [this message]
2026-08-12 8:01 ` [BlueZ, v4 3/9] unit: Add test for sdp-xml type-confusion bug Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 4/9] sdp-xml: Fix memory leak when adding duplicate attributes Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 5/9] unit: Add test for sdp-xml duplicate attribute bug Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 6/9] sdp-xml: Optimise parsing large sequences Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 7/9] unit: Add test for slow element_end() append Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 8/9] sdp-xml: Fix stack overflow when converting large sequences to XML Bastien Nocera
2026-08-12 8:01 ` [BlueZ, v4 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=20260812080410.2116906-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox