Skip to content

Commit b665e4c

Browse files
author
Jyri Sarha
committed
tools: tplg_parser: add bounds checking to topology object reader macros
Add tplg_check_bounds() macro that validates ctx->tplg_offset + advance does not exceed ctx->tplg_size before advancing the offset. Apply this check in all topology object reader macros: tplg_get_hdr, tplg_skip_hdr_payload, tplg_get_object, tplg_get_object_priv, tplg_get_widget, tplg_get_graph, and tplg_get_pcm. Without these checks, a crafted .tplg file with malicious payload_size or priv.size values can drive the offset past the end of the mapped topology data, causing out-of-bounds reads in all subsequent object parsing. Signed-off-by: Jyri Sarha <jyri.sarha@intel.com>
1 parent 29b4ae3 commit b665e4c

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

tools/tplg_parser/include/tplg_parser/topology.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <stdbool.h>
1414
#include <stdarg.h>
1515
#include <stddef.h>
16+
#include <assert.h>
17+
#include <stdio.h>
1618
#include <ipc/dai.h>
1719
#include <ipc/topology.h>
1820
#include <ipc/stream.h>
@@ -194,8 +196,20 @@ struct tplg_context {
194196

195197
#define tplg_get(ctx) ((void *)(ctx->tplg_base + ctx->tplg_offset))
196198

199+
#define tplg_check_bounds(ctx, advance) \
200+
do { \
201+
if ((long)(advance) < 0 || \
202+
ctx->tplg_offset + (long)(advance) > (long)ctx->tplg_size) { \
203+
printf("%s %d topology offset %ld + %ld > size %zu\n", \
204+
__func__, __LINE__, ctx->tplg_offset, \
205+
(long)(advance), ctx->tplg_size); \
206+
assert(0); \
207+
} \
208+
} while (0)
209+
197210
#define tplg_get_hdr(ctx) \
198211
({struct snd_soc_tplg_hdr *ptr; \
212+
tplg_check_bounds(ctx, sizeof(*ptr)); \
199213
ptr = (struct snd_soc_tplg_hdr *)(ctx->tplg_base + ctx->tplg_offset); \
200214
if (ptr->size != sizeof(*ptr)) { \
201215
printf("%s %d hdr size mismatch 0x%x:0x%zx at offset %ld\n", \
@@ -206,30 +220,40 @@ struct tplg_context {
206220

207221
#define tplg_skip_hdr_payload(ctx) \
208222
({struct snd_soc_tplg_hdr *ptr; \
223+
tplg_check_bounds(ctx, hdr->payload_size); \
209224
ptr = (struct snd_soc_tplg_hdr *)(ctx->tplg_base + ctx->tplg_offset); \
210225
ctx->tplg_offset += hdr->payload_size; (void *)ptr; })
211226

212227
#define tplg_get_object(ctx, obj) \
213-
({void *ptr; ptr = ctx->tplg_base + ctx->tplg_offset; \
228+
({void *ptr; \
229+
tplg_check_bounds(ctx, sizeof(*(obj))); \
230+
ptr = ctx->tplg_base + ctx->tplg_offset; \
214231
ctx->tplg_offset += sizeof(*(obj)); ptr; })
215232

216233
#define tplg_get_object_priv(ctx, obj, priv_size) \
217-
({void *ptr; ptr = ctx->tplg_base + ctx->tplg_offset; \
234+
({void *ptr; \
235+
tplg_check_bounds(ctx, sizeof(*(obj)) + (priv_size)); \
236+
ptr = ctx->tplg_base + ctx->tplg_offset; \
218237
ctx->tplg_offset += sizeof(*(obj)) + priv_size; ptr; })
219238

220239
#define tplg_get_widget(ctx) \
221240
({struct snd_soc_tplg_dapm_widget *w; \
241+
tplg_check_bounds(ctx, sizeof(*w)); \
222242
w = (struct snd_soc_tplg_dapm_widget *)(ctx->tplg_base + ctx->tplg_offset); \
243+
tplg_check_bounds(ctx, sizeof(*w) + w->priv.size); \
223244
ctx->tplg_offset += sizeof(*w) + w->priv.size; w; })
224245

225246
#define tplg_get_graph(ctx) \
226247
({struct snd_soc_tplg_dapm_graph_elem *w; \
248+
tplg_check_bounds(ctx, sizeof(*w)); \
227249
w = (struct snd_soc_tplg_dapm_graph_elem *)(ctx->tplg_base + ctx->tplg_offset); \
228250
ctx->tplg_offset += sizeof(*w); w; })
229251

230252
#define tplg_get_pcm(ctx) \
231253
({struct snd_soc_tplg_pcm *pcm; \
254+
tplg_check_bounds(ctx, sizeof(*pcm)); \
232255
pcm = (struct snd_soc_tplg_pcm *)(ctx->tplg_base + ctx->tplg_offset); \
256+
tplg_check_bounds(ctx, sizeof(*pcm) + pcm->priv.size); \
233257
ctx->tplg_offset += sizeof(*pcm) + pcm->priv.size; pcm; })
234258

235259
static inline int tplg_valid_widget(struct snd_soc_tplg_dapm_widget *widget)

0 commit comments

Comments
 (0)