ASoC: msm: check payload size before memory allocation
Buffer from mixer ctl or ADSP is composed of payload size and
actual payload. On a 32 bit platform, we could have an overflow
if payload size is below UINT_MAX while payload size + sizeof(struct)
is over UINT_MAX. Allocated memory size would be less than expected.
Check payload size against limit before memory allocation.
Change-Id: I0bf19ca7b8c93083177a21ad726122dc20f45551
Signed-off-by: Xiaojun Sang <xsang@codeaurora.org>
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index 586683c..edc830a 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -3691,8 +3691,8 @@
goto done;
}
- if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >=
- sizeof(ucontrol->value.bytes.data)) {
+ if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
+ - sizeof(struct msm_adsp_event_data)) {
pr_err("%s param length=%d exceeds limit",
__func__, event_data->payload_len);
ret = -EINVAL;
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index abadc87..e64a7cd 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1152,8 +1152,8 @@
goto done;
}
- if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >=
- sizeof(ucontrol->value.bytes.data)) {
+ if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
+ - sizeof(struct msm_adsp_event_data)) {
pr_err("%s param length=%d exceeds limit",
__func__, event_data->payload_len);
ret = -EINVAL;
diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c
index 00a29d7..ca86dc7 100644
--- a/asoc/msm-qti-pp-config.c
+++ b/asoc/msm-qti-pp-config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -999,8 +999,9 @@
event_data = (struct msm_adsp_event_data *)payload;
kctl->info(kctl, &kctl_info);
- if (sizeof(struct msm_adsp_event_data)
- + event_data->payload_len > kctl_info.count) {
+
+ if (event_data->payload_len >
+ kctl_info.count - sizeof(struct msm_adsp_event_data)) {
pr_err("%s: payload length exceeds limit of %u bytes.\n",
__func__, kctl_info.count);
ret = -EINVAL;
diff --git a/asoc/msm-transcode-loopback-q6-v2.c b/asoc/msm-transcode-loopback-q6-v2.c
index 726133a..7598255 100644
--- a/asoc/msm-transcode-loopback-q6-v2.c
+++ b/asoc/msm-transcode-loopback-q6-v2.c
@@ -549,8 +549,8 @@
goto done;
}
- if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >=
- sizeof(ucontrol->value.bytes.data)) {
+ if (event_data->payload_len > sizeof(ucontrol->value.bytes.data)
+ - sizeof(struct msm_adsp_event_data)) {
pr_err("%s param length=%d exceeds limit",
__func__, event_data->payload_len);
ret = -EINVAL;
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 9fb5d6b..7fe586f 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -2263,6 +2263,14 @@
* package is composed of event type + size + actual payload
*/
payload_size = data->payload_size;
+ if (payload_size > UINT_MAX
+ - sizeof(struct msm_adsp_event_data)) {
+ pr_err("%s: payload size = %d exceeds limit.\n",
+ __func__, payload_size);
+ spin_unlock(&(session[session_id].session_lock));
+ return -EINVAL;
+ }
+
pp_event_package = kzalloc(payload_size
+ sizeof(struct msm_adsp_event_data),
GFP_ATOMIC);