Skip to content

Commit 7604e1a

Browse files
ujfalusibardliao
authored andcommitted
ASoC: SOF: ipc3-control: Fix heap overflow in bytes_ext put/get
The ipc_control_data buffer is allocated as kzalloc(max_size), where max_size covers the entire struct sof_ipc_ctrl_data including its flexible array payload. However, the bounds checks in bytes_ext_put and _bytes_ext_get compared user data lengths against max_size directly, ignoring that cdata->data sits at an offset of sizeof(struct sof_ipc_ctrl_data) bytes into the allocation. This allowed writing up to sizeof(struct sof_ipc_ctrl_data) bytes past the end of the heap buffer from unprivileged userspace via the ALSA TLV kcontrol interface, and similarly allowed over-reading adjacent heap data on the get path. Fix all bounds checks to subtract sizeof(*cdata) from max_size so they reflect the actual space available at the cdata->data offset. Also fix the error-path restore in bytes_ext_put which wrote to cdata->data instead of cdata, causing the same overflow. Fixes: 67ec2a0 ("ASoC: SOF: Add bytes_ext control IPC ops for IPC3") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent b6f95f1 commit 7604e1a

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

sound/soc/sof/ipc3-control.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,17 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
398398
}
399399

400400
/* be->max is coming from topology */
401-
if (header.length > scontrol->max_size) {
402-
dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n",
403-
header.length, scontrol->max_size);
401+
if (header.length > scontrol->max_size - sizeof(*cdata)) {
402+
dev_err_ratelimited(scomp->dev, "Bytes data size %u exceeds max %zu\n",
403+
header.length, scontrol->max_size - sizeof(*cdata));
404+
return -EINVAL;
405+
}
406+
407+
/* Ensure the data is large enough to contain the ABI header */
408+
if (header.length < sizeof(struct sof_abi_hdr)) {
409+
dev_err_ratelimited(scomp->dev,
410+
"Bytes data size %u less than ABI header %zu\n",
411+
header.length, sizeof(struct sof_abi_hdr));
404412
return -EINVAL;
405413
}
406414

@@ -436,7 +444,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
436444
}
437445

438446
/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
439-
if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
447+
if (cdata->data->size > scontrol->max_size - sizeof(*cdata) - sizeof(struct sof_abi_hdr)) {
440448
dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n");
441449
goto err_restore;
442450
}
@@ -452,7 +460,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
452460
err_restore:
453461
/* If we have an issue, we restore the old, valid bytes control data */
454462
if (scontrol->old_ipc_control_data) {
455-
memcpy(cdata->data, scontrol->old_ipc_control_data, scontrol->max_size);
463+
memcpy(cdata, scontrol->old_ipc_control_data, scontrol->max_size);
456464
kfree(scontrol->old_ipc_control_data);
457465
scontrol->old_ipc_control_data = NULL;
458466
}
@@ -491,10 +499,13 @@ static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
491499
}
492500

493501
/* check data size doesn't exceed max coming from topology */
494-
if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
495-
dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n",
502+
if (cdata->data->size > scontrol->max_size - sizeof(*cdata) -
503+
sizeof(struct sof_abi_hdr)) {
504+
dev_err_ratelimited(scomp->dev,
505+
"User data size %u exceeds max size %zu\n",
496506
cdata->data->size,
497-
scontrol->max_size - sizeof(struct sof_abi_hdr));
507+
scontrol->max_size - sizeof(*cdata) -
508+
sizeof(struct sof_abi_hdr));
498509
return -EINVAL;
499510
}
500511

0 commit comments

Comments
 (0)