From 06900eba2d944d1fb4279c6714cf926bd3d58b77 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 11 Jun 2026 10:43:48 +0200 Subject: [PATCH 1/3] audio: data_blob: fix memcpy_s bounds in ipc4_comp_data_blob_set Pass the real destination capacity instead of the copy count so the size check is effective, preventing a host-controlled heap overflow of data_new. Signed-off-by: Adrian Bonislawski --- src/audio/data_blob.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c index 399244106f95..0a2931436412 100644 --- a/src/audio/data_blob.c +++ b/src/audio/data_blob.c @@ -365,8 +365,16 @@ int ipc4_comp_data_blob_set(struct comp_data_blob_handler *blob_handler, valid_data_size = last_block ? data_offset : MAILBOX_DSPBOX_SIZE; ret = memcpy_s((char *)blob_handler->data_new, - valid_data_size, data, valid_data_size); - assert(!ret); + blob_handler->new_data_size, data, valid_data_size); + if (ret) { + comp_err(blob_handler->dev, "failed to copy fragment"); + blob_handler->free(blob_handler->data_new); + blob_handler->data_new = NULL; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + blob_handler->data_ready = false; + return ret; + } blob_handler->data_pos += valid_data_size; } else { @@ -391,8 +399,17 @@ int ipc4_comp_data_blob_set(struct comp_data_blob_handler *blob_handler, valid_data_size = blob_handler->new_data_size - data_offset; ret = memcpy_s((char *)blob_handler->data_new + data_offset, - valid_data_size, data, valid_data_size); - assert(!ret); + blob_handler->new_data_size - data_offset, + data, valid_data_size); + if (ret) { + comp_err(blob_handler->dev, "failed to copy fragment"); + blob_handler->free(blob_handler->data_new); + blob_handler->data_new = NULL; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + blob_handler->data_ready = false; + return ret; + } blob_handler->data_pos += valid_data_size; } From 6d5cf824ba82b59827c7f199cb992644e28fad79 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 11 Jun 2026 14:24:44 +0200 Subject: [PATCH 2/3] audio: data_blob: reject first_block while transfer in progress ipc4_comp_data_blob_set() had no busy check, so a new first_block received mid-transfer skipped reallocation but still updated new_data_size, defeating the memcpy_s bound and allowing a host-controlled heap overflow. Reject it with -EBUSY, mirroring comp_data_blob_set() and comp_data_blob_set_cmd(). Signed-off-by: Adrian Bonislawski --- src/audio/data_blob.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c index 0a2931436412..0849107afe11 100644 --- a/src/audio/data_blob.c +++ b/src/audio/data_blob.c @@ -330,6 +330,14 @@ int ipc4_comp_data_blob_set(struct comp_data_blob_handler *blob_handler, "data_offset = %d", data_offset); + /* Reject a new first_block mid-transfer: reusing stale data_new while + * overwriting new_data_size defeats the memcpy_s bound (heap overflow). + */ + if (blob_handler->data_new && first_block) { + comp_err(blob_handler->dev, "busy with previous request"); + return -EBUSY; + } + /* in case when the current package is the first, we should allocate * memory for whole model data */ From 45f3f05dbe0188bcb0d25122701c289781155fcd Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 11 Jun 2026 14:24:54 +0200 Subject: [PATCH 3/3] audio: data_blob: bound blob read against data_size comp_data_blob_get_cmd() advanced data_pos by the host-controlled num_elems each fragment with no check against the blob size, so a fragmented bytes-get could read past the blob and leak adjacent DSP heap to the host. Reject reads where data_pos or num_elems exceed data_size. Signed-off-by: Adrian Bonislawski --- src/audio/data_blob.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c index 0849107afe11..88288a9d44b1 100644 --- a/src/audio/data_blob.c +++ b/src/audio/data_blob.c @@ -628,6 +628,18 @@ int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, return -EINVAL; } + /* Bound data_pos against data_size: host-controlled num_elems + * advances it per fragment and could leak adjacent heap. + */ + if (blob_handler->data_pos >= blob_handler->data_size || + cdata->num_elems > blob_handler->data_size - blob_handler->data_pos) { + comp_err(blob_handler->dev, + "out of bounds read: pos %u elems %u size %u", + blob_handler->data_pos, cdata->num_elems, + blob_handler->data_size); + return -EINVAL; + } + /* copy required size of data */ ret = memcpy_s(cdata->data->data, size, (char *)blob_handler->data + blob_handler->data_pos,