Skip to content

Commit 95edf2d

Browse files
Yousef13710broonie
authored andcommitted
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>
1 parent e782d68 commit 95edf2d

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

sound/soc/sof/sof-client-probes-ipc3.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
107107
struct device *dev = &cdev->auxdev.dev;
108108
struct sof_ipc_probe_info_params msg = {{{0}}};
109109
struct sof_ipc_probe_info_params *reply;
110-
size_t bytes;
110+
size_t bytes, elem_size, payload_size;
111111
int ret;
112112

113113
*params = NULL;
@@ -128,14 +128,29 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
128128
if (ret < 0 || reply->rhdr.error < 0)
129129
goto exit;
130130

131+
payload_size = reply->rhdr.hdr.size;
132+
if (payload_size < offsetof(struct sof_ipc_probe_info_params, dma)) {
133+
ret = -EINVAL;
134+
goto exit;
135+
}
136+
131137
if (!reply->num_elems)
132138
goto exit;
133139

134140
if (cmd == SOF_IPC_PROBE_DMA_INFO)
135-
bytes = sizeof(reply->dma[0]);
141+
elem_size = sizeof(reply->dma[0]);
136142
else
137-
bytes = sizeof(reply->desc[0]);
138-
bytes *= reply->num_elems;
143+
elem_size = sizeof(reply->desc[0]);
144+
145+
payload_size -= offsetof(struct sof_ipc_probe_info_params, dma);
146+
if (reply->num_elems > payload_size / elem_size) {
147+
dev_err(dev, "%s: invalid probe info element count %u\n",
148+
__func__, reply->num_elems);
149+
ret = -EINVAL;
150+
goto exit;
151+
}
152+
153+
bytes = reply->num_elems * elem_size;
139154
*params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL);
140155
if (!*params) {
141156
ret = -ENOMEM;

sound/soc/sof/sof-client-probes-ipc4.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,19 @@ static int ipc4_probes_points_info(struct sof_client_dev *cdev,
248248
return ret;
249249
}
250250
info = msg.data_ptr;
251+
if (msg.data_size < sizeof(*info) ||
252+
info->num_elems > (msg.data_size - sizeof(*info)) /
253+
sizeof(info->points[0])) {
254+
dev_err(dev, "%s: invalid probe info element count %u\n",
255+
__func__, info->num_elems);
256+
kfree(msg.data_ptr);
257+
return -EINVAL;
258+
}
259+
251260
*num_desc = info->num_elems;
252261
dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc);
253262

254-
*desc = kzalloc(*num_desc * sizeof(**desc), GFP_KERNEL);
263+
*desc = kcalloc(*num_desc, sizeof(**desc), GFP_KERNEL);
255264
if (!*desc) {
256265
kfree(msg.data_ptr);
257266
return -ENOMEM;

0 commit comments

Comments
 (0)