summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Lee <lerobert@google.com>2019-11-06 19:05:15 +0800
committerHarrison Lingren <hlingren@google.com>2020-01-06 18:40:07 +0000
commit972a37bccd990dae69414c545534f705ca25f1f2 (patch)
tree32dcf2698b22e406b84d0bf4d701566f8f3fadf8
parent33947067e30ceac232d167c12af9fb523b0fa79d (diff)
downloadmsm-extra-972a37bccd990dae69414c545534f705ca25f1f2.tar.gz
audio: secure copy size for kernel memory
add size checking to prevent memcpy access out of bound. Bug: 139739561 Test: speaker playback ok Change-Id: If00af6a97cc8ab80776179ff0b81ad99e667b3d3 Signed-off-by: Robert Lee <lerobert@google.com>
-rw-r--r--asoc/msm-cirrus-playback.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/asoc/msm-cirrus-playback.c b/asoc/msm-cirrus-playback.c
index 0eb6e045..50e813ef 100644
--- a/asoc/msm-cirrus-playback.c
+++ b/asoc/msm-cirrus-playback.c
@@ -40,6 +40,7 @@ static struct crus_single_data_t crus_enable;
static struct crus_sp_ioctl_header crus_sp_hdr;
static struct cirrus_cal_result_t crus_sp_cal_rslt;
static int32_t *crus_sp_get_buffer;
+static int32_t crus_sp_get_buffer_size;
static atomic_t crus_sp_get_param_flag;
struct mutex crus_sp_get_param_lock;
struct mutex crus_sp_lock;
@@ -198,8 +199,8 @@ static int crus_afe_get_param(int port, int module, int param, int length,
mutex_lock(&crus_sp_get_param_lock);
atomic_set(&crus_sp_get_param_flag, 0);
- crus_sp_get_buffer = kzalloc(config->param.payload_size + 16,
- GFP_KERNEL);
+ crus_sp_get_buffer_size = config->param.payload_size + 16;
+ crus_sp_get_buffer = kzalloc(crus_sp_get_buffer_size, GFP_KERNEL);
if (!crus_sp_get_buffer) {
pr_err("%s: kzalloc failed for crus_sp_get_buffer!\n",
@@ -233,6 +234,7 @@ static int crus_afe_get_param(int port, int module, int param, int length,
crus_sp_get_param_err:
kfree(crus_sp_get_buffer);
crus_sp_get_buffer = NULL;
+ crus_sp_get_buffer_size = -1;
crus_sp_get_buffer_err:
mutex_unlock(&crus_sp_get_param_lock);
@@ -441,13 +443,22 @@ static int crus_afe_send_delta(const char *data, uint32_t length)
extern int crus_afe_callback(void *payload, int size)
{
uint32_t *payload32 = payload;
+ int copysize;
pr_debug("Cirrus AFE CALLBACK: size = %d\n", size);
+ if (size < 8)
+ return -EINVAL;
switch (payload32[1]) {
case CIRRUS_SP:
if (crus_sp_get_buffer != NULL) {
- memcpy(crus_sp_get_buffer, payload32, size);
+ copysize = (crus_sp_get_buffer_size > size) ?
+ size : crus_sp_get_buffer_size;
+
+ if (copysize != size)
+ pr_warn("size mismatch data may lost\n");
+
+ memcpy(crus_sp_get_buffer, payload32, copysize);
atomic_set(&crus_sp_get_param_flag, 1);
}
break;