summaryrefslogtreecommitdiff
path: root/sound/soc/sof/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/control.c')
-rw-r--r--sound/soc/sof/control.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c
index 63ead9ebc4c6..58f8c998e6af 100644
--- a/sound/soc/sof/control.c
+++ b/sound/soc/sof/control.c
@@ -229,14 +229,16 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
return -EINVAL;
}
- size = data->size + sizeof(*data);
- if (size > be->max) {
+ /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
+ if (data->size > be->max - sizeof(*data)) {
dev_err_ratelimited(scomp->dev,
- "error: DSP sent %zu bytes max is %d\n",
- size, be->max);
+ "error: %u bytes of control data is invalid, max is %zu\n",
+ data->size, be->max - sizeof(*data));
return -EINVAL;
}
+ size = data->size + sizeof(*data);
+
/* copy back to kcontrol */
memcpy(ucontrol->value.bytes.data, data, size);
@@ -252,7 +254,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct sof_abi_hdr *data = cdata->data;
- size_t size = data->size + sizeof(*data);
+ size_t size;
if (be->max > sizeof(ucontrol->value.bytes.data)) {
dev_err_ratelimited(scomp->dev,
@@ -261,13 +263,16 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
}
- if (size > be->max) {
+ /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
+ if (data->size > be->max - sizeof(*data)) {
dev_err_ratelimited(scomp->dev,
- "error: size too big %zu bytes max is %d\n",
- size, be->max);
+ "error: data size too big %u bytes max is %zu\n",
+ data->size, be->max - sizeof(*data));
return -EINVAL;
}
+ size = data->size + sizeof(*data);
+
/* copy from kcontrol */
memcpy(data, ucontrol->value.bytes.data, size);
@@ -334,7 +339,8 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
}
- if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) {
+ /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
+ if (cdata->data->size > be->max - sizeof(const struct sof_abi_hdr)) {
dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n");
return -EINVAL;
}
@@ -420,7 +426,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_tlv header;
struct snd_ctl_tlv __user *tlvd =
(struct snd_ctl_tlv __user *)binary_data;
- int data_size;
+ size_t data_size;
/*
* Decrement the limit by ext bytes header size to
@@ -432,16 +438,16 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
cdata->data->magic = SOF_ABI_MAGIC;
cdata->data->abi = SOF_ABI_VERSION;
- /* Prevent read of other kernel data or possibly corrupt response */
- data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
-
/* check data size doesn't exceed max coming from topology */
- if (data_size > be->max) {
- dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %d.\n",
- data_size, be->max);
+ if (cdata->data->size > be->max - sizeof(const struct sof_abi_hdr)) {
+ dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
+ cdata->data->size,
+ be->max - sizeof(const struct sof_abi_hdr));
return -EINVAL;
}
+ data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
+
header.numid = scontrol->cmd;
header.length = data_size;
if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv)))