ASoC: SOF: validate probe info element counts

Probe information replies contain a firmware-provided element count. IPC3
uses that count to copy an array, then returns the unchecked count to its
caller. A short reply can therefore make the caller walk beyond the copied
array.

IPC4 similarly uses the count both to allocate the destination array and
to walk the reply. On 32-bit systems the allocation size can wrap, while on
all systems an excessive count reads beyond the reply payload.

Validate each count against the actual reply size before copying or
allocating the array, and use kcalloc() for the IPC4 allocation.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Link: https://patch.msgid.link/20260628000329.18606-1-alhouseenyousef@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Yousef Alhouseen 2026-06-28 02:03:29 +02:00 committed by Mark Brown
parent e782d687d2
commit 95edf2dbb4
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 29 additions and 5 deletions

View File

@ -107,7 +107,7 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
struct device *dev = &cdev->auxdev.dev;
struct sof_ipc_probe_info_params msg = {{{0}}};
struct sof_ipc_probe_info_params *reply;
size_t bytes;
size_t bytes, elem_size, payload_size;
int ret;
*params = NULL;
@ -128,14 +128,29 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
if (ret < 0 || reply->rhdr.error < 0)
goto exit;
payload_size = reply->rhdr.hdr.size;
if (payload_size < offsetof(struct sof_ipc_probe_info_params, dma)) {
ret = -EINVAL;
goto exit;
}
if (!reply->num_elems)
goto exit;
if (cmd == SOF_IPC_PROBE_DMA_INFO)
bytes = sizeof(reply->dma[0]);
elem_size = sizeof(reply->dma[0]);
else
bytes = sizeof(reply->desc[0]);
bytes *= reply->num_elems;
elem_size = sizeof(reply->desc[0]);
payload_size -= offsetof(struct sof_ipc_probe_info_params, dma);
if (reply->num_elems > payload_size / elem_size) {
dev_err(dev, "%s: invalid probe info element count %u\n",
__func__, reply->num_elems);
ret = -EINVAL;
goto exit;
}
bytes = reply->num_elems * elem_size;
*params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL);
if (!*params) {
ret = -ENOMEM;

View File

@ -248,10 +248,19 @@ static int ipc4_probes_points_info(struct sof_client_dev *cdev,
return ret;
}
info = msg.data_ptr;
if (msg.data_size < sizeof(*info) ||
info->num_elems > (msg.data_size - sizeof(*info)) /
sizeof(info->points[0])) {
dev_err(dev, "%s: invalid probe info element count %u\n",
__func__, info->num_elems);
kfree(msg.data_ptr);
return -EINVAL;
}
*num_desc = info->num_elems;
dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc);
*desc = kzalloc(*num_desc * sizeof(**desc), GFP_KERNEL);
*desc = kcalloc(*num_desc, sizeof(**desc), GFP_KERNEL);
if (!*desc) {
kfree(msg.data_ptr);
return -ENOMEM;