[PATCH] greybus: audio: bound the topology section sizes against the fetched size

From: Bryam Vargas via B4 Relay

Date: Tue Jun 16 2026 - 02:07:02 EST


From: Bryam Vargas <hexlabsecurity@xxxxxxxxx>

gb_audio_gb_get_topology() fetches a topology blob of a module-supplied
size, and gbaudio_tplg_parse_data() then walks it by adding the
module-supplied size_dais, size_controls and size_widgets fields to
form the control, widget and route section offsets. Those le32 sizes
are never checked against the fetched blob, so a module reporting a
small topology size but large section sizes makes the offsets point
past the allocation, and parsing reads out of bounds.

Reject a topology whose section sizes do not fit within the fetched
size before it is parsed.

Fixes: 184992e305f1 ("greybus: audio: Add Greybus Audio Device Class Protocol helper routines")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
---
I reproduced the out-of-bounds read both in-kernel under KASAN and with
a userspace AddressSanitizer model of the gbaudio_tplg_process_header()
offset walk. The topology blob is kzalloc(size) where size is
module-supplied (a u16), and process_header() forms control_offset =
&data + size_dais, widget_offset = control_offset + size_controls, etc.;
the consumers then read structs at those offsets.

- In-kernel (7.1.0-rc5 + KASAN): a 64-byte blob (header 24, so 40 bytes
available) with size_dais = 44 makes control_offset point 4 bytes
past the allocation, and reading the first control byte there trips:

BUG: KASAN: slab-out-of-bounds in ...parse_topology...
Read of size 1 at addr ...
... which belongs to the cache kmalloc-64 of size 64
The buggy address is located 4 bytes to the right of
allocated 64-byte region

The patched arm (sections rejected, -EINVAL) and an in-bounds control
arm (size_dais = 8) read cleanly with no KASAN report.
- ASan model (-m32 and -m64): size_dais = 4096 makes control_offset
point ~4 KB past the 64-byte blob - heap-buffer-overflow READ located
4056 bytes after the region, both ABIs; patched and in-bounds clean.

The source is a greybus audio module trust boundary (an attacker-supplied
or compromised module reporting a malformed topology); the access is a
read, and a large size_dais sends the offset far enough to fault. The
reproducer (kernel module + ASan model) is available on request.
---
drivers/staging/greybus/audio_gb.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c
index 9d8994fdb41a..144591f1a512 100644
--- a/drivers/staging/greybus/audio_gb.c
+++ b/drivers/staging/greybus/audio_gb.c
@@ -37,6 +37,19 @@ int gb_audio_gb_get_topology(struct gb_connection *connection,
return ret;
}

+ /*
+ * The size_* fields are supplied by the module and are used by
+ * gbaudio_tplg_parse_data() to compute offsets into the blob; make
+ * sure the sections fit within the fetched topology, so walking it
+ * cannot read out of bounds.
+ */
+ if ((u64)le32_to_cpu(topo->size_dais) + le32_to_cpu(topo->size_controls) +
+ le32_to_cpu(topo->size_widgets) + le32_to_cpu(topo->size_routes) >
+ size - sizeof(*topo)) {
+ kfree(topo);
+ return -EINVAL;
+ }
+
*topology = topo;

return 0;

---
base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
change-id: 20260616-b4-disp-4352e8b0-45e86659956e

Best regards,
--
Bryam Vargas <hexlabsecurity@xxxxxxxxx>