mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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:
parent
e782d687d2
commit
95edf2dbb4
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user