aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilson Sung <wilsonsung@google.com>2019-07-12 11:43:24 +0800
committerWilson Sung <wilsonsung@google.com>2019-07-12 11:46:37 +0800
commit382d7256ce446a4896ceaa244c1eacd7606bef67 (patch)
tree92f9541b82404d98a888292cf3f1ce48a2d9ebd0
parent9414e6c5024ad5060c57a8cb9364196b39fe9a95 (diff)
parentb958c2c73702bb691b064322125ee9af8f3f657b (diff)
Merge branch 'android-msm-marlin-3.18-security-next' into android-msm-marlin-3.18android-q-preview-6_r0.1android-10.0.0_r0.1
SEP 2019.1 Bug: 136171073 Change-Id: I18bb18fef1f987b1cb5bcfa1362781e2bd19b759 Signed-off-by: Wilson Sung <wilsonsung@google.com>
-rw-r--r--drivers/char/diag/diagchar_core.c21
-rw-r--r--drivers/gpu/msm/kgsl.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c8
-rw-r--r--drivers/soc/qcom/qdsp6v2/voice_svc.c60
-rw-r--r--drivers/staging/android/binder.c12
-rw-r--r--include/sound/q6lsm.h4
-rw-r--r--sound/soc/msm/qdsp6v2/msm-lsm-client.c39
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c176
-rw-r--r--sound/soc/msm/qdsp6v2/q6lsm.c17
9 files changed, 263 insertions, 78 deletions
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index bae913a131b1..bf1d3fb97bb9 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -519,8 +519,8 @@ static int diag_remove_client_entry(struct file *file)
static int diagchar_close(struct inode *inode, struct file *file)
{
int ret;
- DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n",
- current->comm);
+ DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: %s process exit with pid = %d\n",
+ current->comm, current->tgid);
ret = diag_remove_client_entry(file);
mutex_lock(&driver->diag_maskclear_mutex);
driver->mask_clear = 0;
@@ -2830,6 +2830,8 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
int exit_stat = 0;
int write_len = 0;
struct diag_md_session_t *session_info = NULL;
+ struct pid *pid_struct = NULL;
+ struct task_struct *task_s = NULL;
mutex_lock(&driver->diagchar_mutex);
for (i = 0; i < driver->num_clients; i++)
@@ -3025,8 +3027,19 @@ exit:
list_for_each_safe(start, temp, &driver->dci_client_list) {
entry = list_entry(start, struct diag_dci_client_tbl,
track);
- if (entry->client->tgid != current->tgid)
+ pid_struct = find_get_pid(entry->tgid);
+ if (!pid_struct)
continue;
+ task_s = get_pid_task(pid_struct, PIDTYPE_PID);
+ if (!task_s) {
+ DIAG_LOG(DIAG_DEBUG_DCI,
+ "diag: valid task doesn't exist for pid = %d\n",
+ entry->tgid);
+ continue;
+ }
+ if (task_s == entry->client)
+ if (entry->client->tgid != current->tgid)
+ continue;
if (!entry->in_service)
continue;
if (copy_to_user(buf + ret, &data_type, sizeof(int))) {
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 5f302d0559b0..8122f6ecbf87 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -318,7 +318,7 @@ kgsl_mem_entry_destroy(struct kref *kref)
entry->memdesc.sgt->nents, i) {
page = sg_page(sg);
for (j = 0; j < (sg->length >> PAGE_SHIFT); j++)
- set_page_dirty(nth_page(page, j));
+ set_page_dirty_lock(nth_page(page, j));
}
}
diff --git a/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c
index 51a9ea85d1f3..cfb7486d6eb8 100644
--- a/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c
+++ b/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2011-2014,2017-2019,The Linux Foundataion. 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
@@ -354,12 +354,13 @@ int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
}
} else {
for (i = num_clk - 1; i >= 0; i--) {
- if (clk_ptr[i] != NULL) {
+ if (!IS_ERR_OR_NULL(clk_ptr[i])) {
CDBG("%s disable %s\n", __func__,
clk_info[i].clk_name);
clk_disable(clk_ptr[i]);
clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]);
+ clk_ptr[i] = NULL;
}
}
}
@@ -373,10 +374,11 @@ cam_clk_set_err:
clk_put(clk_ptr[i]);
cam_clk_get_err:
for (i--; i >= 0; i--) {
- if (clk_ptr[i] != NULL) {
+ if (!IS_ERR_OR_NULL(clk_ptr[i])) {
clk_disable(clk_ptr[i]);
clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]);
+ clk_ptr[i] = NULL;
}
}
return rc;
diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c
index 8cd2ed6e2fab..a15bd75aecc9 100644
--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c
+++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, 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
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
@@ -67,7 +68,12 @@ static void *dummy_q6_mvm;
static void *dummy_q6_cvs;
dev_t device_num;
+struct mutex session_lock;
+static spinlock_t voicesvc_lock;
+static bool is_released = 1;
static int voice_svc_dummy_reg(void);
+static int voice_svc_dummy_dereg(void);
+
static int32_t qdsp_dummy_apr_callback(struct apr_client_data *data,
void *priv);
@@ -82,10 +88,16 @@ static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv)
return -EINVAL;
}
+ spin_lock(&voicesvc_lock);
+ if (is_released) {
+ spin_unlock(&voicesvc_lock);
+ return 0;
+ }
prtd = (struct voice_svc_prvt *)priv;
if (prtd == NULL) {
pr_err("%s: private data is NULL\n", __func__);
+ spin_unlock(&voicesvc_lock);
return -EINVAL;
}
@@ -128,6 +140,7 @@ static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv)
spin_unlock_irqrestore(&prtd->response_lock,
spin_flags);
+ spin_unlock(&voicesvc_lock);
return -ENOMEM;
}
@@ -156,6 +169,7 @@ static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv)
__func__);
}
+ spin_unlock(&voicesvc_lock);
return 0;
}
@@ -614,17 +628,41 @@ err:
return -EINVAL;
}
+static int voice_svc_dummy_dereg(void)
+{
+ pr_debug("%s\n", __func__);
+ if (dummy_q6_mvm != NULL) {
+ apr_deregister(dummy_q6_mvm);
+ dummy_q6_mvm = NULL;
+ }
+
+ if (dummy_q6_cvs != NULL) {
+ apr_deregister(dummy_q6_cvs);
+ dummy_q6_cvs = NULL;
+ }
+ return 0;
+}
+
static int voice_svc_open(struct inode *inode, struct file *file)
{
struct voice_svc_prvt *prtd = NULL;
+ int ret = 0;
pr_info("%s\n", __func__); // HTC_AUD_MOD
+ mutex_lock(&session_lock);
+ if (is_released == 0) {
+ pr_err("%s: Access denied to device\n", __func__);
+ ret = -EBUSY;
+ goto done;
+ }
+
prtd = kmalloc(sizeof(struct voice_svc_prvt), GFP_KERNEL);
if (prtd == NULL) {
pr_err("%s: kmalloc failed\n", __func__);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto done;
}
memset(prtd, 0, sizeof(struct voice_svc_prvt));
@@ -637,6 +675,7 @@ static int voice_svc_open(struct inode *inode, struct file *file)
mutex_init(&prtd->response_mutex_lock);
file->private_data = (void *)prtd;
+ is_released = 0;
/* Current APR implementation doesn't support session based
* multiple service registrations. The apr_deregister()
* function sets the destination and client IDs to zero, if
@@ -647,7 +686,9 @@ static int voice_svc_open(struct inode *inode, struct file *file)
voice_svc_dummy_reg();
reg_dummy_sess = 1;
}
- return 0;
+done:
+ mutex_unlock(&session_lock);
+ return ret;
}
static int voice_svc_release(struct inode *inode, struct file *file)
@@ -669,6 +710,12 @@ static int voice_svc_release(struct inode *inode, struct file *file)
goto done;
}
+ mutex_lock(&prtd->response_mutex_lock);
+ if (reg_dummy_sess) {
+ voice_svc_dummy_dereg();
+ reg_dummy_sess = 0;
+ }
+
if (prtd->apr_q6_cvs != NULL) {
pr_info("%s: voice_svc_dereg VOICE_SVC_CVS_STR\n", __func__); // HTC_AUD_ADD
svc_name = VOICE_SVC_CVS_STR; // HTC_AUD_MOD
@@ -687,7 +734,6 @@ static int voice_svc_release(struct inode *inode, struct file *file)
pr_err("%s: Failed to dereg MVM %d\n", __func__, ret);
}
- mutex_lock(&prtd->response_mutex_lock);
spin_lock_irqsave(&prtd->response_lock, spin_flags);
while (!list_empty(&prtd->response_queue)) {
@@ -705,9 +751,12 @@ static int voice_svc_release(struct inode *inode, struct file *file)
mutex_destroy(&prtd->response_mutex_lock);
+ spin_lock(&voicesvc_lock);
kfree(file->private_data);
file->private_data = NULL;
+ is_released = 1;
+ spin_unlock(&voicesvc_lock);
pr_info("%s --\n", __func__); // HTC_AUD_MOD
done:
@@ -778,6 +827,8 @@ static int voice_svc_probe(struct platform_device *pdev)
goto add_err;
}
pr_debug("%s: Device created\n", __func__);
+ spin_lock_init(&voicesvc_lock);
+ mutex_init(&session_lock);
goto done;
add_err:
@@ -800,6 +851,7 @@ static int voice_svc_remove(struct platform_device *pdev)
kfree(voice_svc_dev->cdev);
device_destroy(voice_svc_class, device_num);
class_destroy(voice_svc_class);
+ mutex_destroy(&session_lock);
unregister_chrdev_region(0, MINOR_NUMBER);
return 0;
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 040532297d13..9a914e8d4539 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -3167,6 +3167,7 @@ static void binder_transaction(struct binder_proc *proc,
if (target_node && target_node->txn_security_ctx) {
u32 secid;
+ size_t added_size;
security_task_getsecid(proc->tsk, &secid);
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
@@ -3176,7 +3177,15 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_get_secctx_failed;
}
- extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+ added_size = ALIGN(secctx_sz, sizeof(u64));
+ extra_buffers_size += added_size;
+ if (extra_buffers_size < added_size) {
+ /* integer overflow of extra_buffers_size */
+ return_error = BR_FAILED_REPLY;
+ return_error_param = EINVAL;
+ return_error_line = __LINE__;
+ goto err_bad_extra_size;
+ }
}
trace_binder_transaction(reply, t, target_node);
@@ -3471,6 +3480,7 @@ err_copy_data_failed:
t->buffer->transaction = NULL;
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
+err_bad_extra_size:
if (secctx)
security_release_secctx(secctx, secctx_sz);
err_get_secctx_failed:
diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h
index fb848bc70873..2b6047c37823 100644
--- a/include/sound/q6lsm.h
+++ b/include/sound/q6lsm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, 2019 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
@@ -22,7 +22,7 @@
#define MAX_NUM_CONFIDENCE 20
typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
- uint32_t *payload, void *priv);
+ uint32_t *payload, uint16_t client_size, void *priv);
struct lsm_sound_model {
dma_addr_t phys;
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 7a0d5d9ddc8a..635f38b12bfb 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, 2019 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
@@ -188,7 +188,8 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd,
}
static void lsm_event_handler(uint32_t opcode, uint32_t token,
- void *payload, void *priv)
+ void *payload, uint16_t client_size,
+ void *priv)
{
unsigned long flags;
struct lsm_priv *prtd = priv;
@@ -254,6 +255,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
}
case LSM_SESSION_EVENT_DETECTION_STATUS:
+ if (client_size < 3 * sizeof(uint8_t)) {
+ dev_err(rtd->dev,
+ "%s: client_size has invalid size[%d]\n",
+ __func__, client_size);
+ return;
+ }
status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[2];
index = 4;
@@ -263,6 +270,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
break;
case LSM_SESSION_EVENT_DETECTION_STATUS_V2:
+ if (client_size < 2 * sizeof(uint8_t)) {
+ dev_err(rtd->dev,
+ "%s: client_size has invalid size[%d]\n",
+ __func__, client_size);
+ return;
+ }
status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[1];
index = 2;
@@ -289,12 +302,22 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
prtd->event_status->status = status;
prtd->event_status->payload_size = payload_size;
if (likely(prtd->event_status)) {
- memcpy(prtd->event_status->payload,
- &((uint8_t *)payload)[index],
- payload_size);
- prtd->event_avail = 1;
- spin_unlock_irqrestore(&prtd->event_lock, flags);
- wake_up(&prtd->event_wait);
+ if (client_size >= (payload_size + index)) {
+ memcpy(prtd->event_status->payload,
+ &((uint8_t *)payload)[index],
+ payload_size);
+ prtd->event_avail = 1;
+ spin_unlock_irqrestore(&prtd->event_lock,
+ flags);
+ wake_up(&prtd->event_wait);
+ } else {
+ spin_unlock_irqrestore(&prtd->event_lock,
+ flags);
+ dev_err(rtd->dev,
+ "%s: Failed to copy memory with invalid size = %d\n",
+ __func__, payload_size);
+ return;
+ }
} else {
spin_unlock_irqrestore(&prtd->event_lock, flags);
dev_err(rtd->dev,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index b3299e13da26..3f8d0ddb5874 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1518,14 +1518,14 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
return 0;
}
- if (data->payload_size > sizeof(int)) {
+ if (data->payload_size >= 2 * sizeof(uint32_t)) {
pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
__func__, payload[0], payload[1], data->opcode,
data->token, data->payload_size, data->src_port,
data->dest_port, sid, dir);
pr_debug("%s:Payload = [0x%x] status[0x%x]\n",
__func__, payload[0], payload[1]);
- } else if (data->payload_size == sizeof(int)) {
+ } else if (data->payload_size == sizeof(uint32_t)) {
pr_debug("%s:ptr0[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
__func__, payload[0], data->opcode,
data->token, data->payload_size, data->src_port,
@@ -1539,7 +1539,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
case ASM_CMD_SHARED_MEM_MAP_REGIONS:
case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
case ASM_CMD_ADD_TOPOLOGIES:
- if (payload[1] != 0) {
+ if (data->payload_size >= 2 * sizeof(uint32_t)
+ && payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
__func__, payload[0], payload[1], sid);
if (payload[0] ==
@@ -1556,8 +1557,12 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1)
wake_up(&ac->mem_wait);
- dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n",
+ if (data->payload_size >= 2 * sizeof(uint32_t))
+ dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n",
__func__, payload[0], payload[1]);
+ else
+ dev_vdbg(ac->dev, "%s: Payload size of %d is less than expected.\n",
+ __func__, data->payload_size);
break;
default:
pr_debug("%s: command[0x%x] not expecting rsp\n",
@@ -1594,8 +1599,13 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
break;
}
case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:{
- pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n",
- __func__, payload[0], payload[1]);
+ if (data->payload_size >= 2 * sizeof(uint32_t))
+ pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n",
+ __func__, payload[0], payload[1]);
+ else
+ pr_debug("%s: Payload size of %d is less than expected.\n",
+ __func__, data->payload_size);
+
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1)
wake_up(&ac->mem_wait);
@@ -1604,8 +1614,12 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
break;
}
default:
- pr_debug("%s: command[0x%x]success [0x%x]\n",
- __func__, payload[0], payload[1]);
+ if (data->payload_size >= 2 * sizeof(uint32_t))
+ pr_debug("%s: command[0x%x]success [0x%x]\n",
+ __func__, payload[0], payload[1]);
+ else
+ pr_debug("%s: Payload size of %d is less than expected.\n",
+ __func__, data->payload_size);
}
if (ac->cb)
ac->cb(data->opcode, data->token,
@@ -1767,8 +1781,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
&(session[session_id].session_lock), flags);
return -EINVAL;
}
- dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n",
- __func__, payload[0], payload[1], data->opcode);
+ if (data->payload_size >= 2 * sizeof(uint32_t))
+ dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n",
+ __func__, payload[0], payload[1], data->opcode);
+ else
+ dev_vdbg(ac->dev, "%s: Payload size of %d is less than expected.\n",
+ __func__, data->payload_size);
}
if (data->opcode == APR_BASIC_RSP_RESULT) {
token = data->token;
@@ -1809,14 +1827,18 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
- pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n",
- __func__, ac->session,
- data->opcode, data->token,
- payload[0], payload[1],
- data->src_port, data->dest_port);
- if (payload[1] != 0) {
+ if (data->payload_size >=
+ 2 * sizeof(uint32_t) &&
+ payload[1] != 0) {
+ pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n",
+ __func__, ac->session,
+ data->opcode, data->token,
+ payload[0], payload[1],
+ data->src_port, data->dest_port);
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
- __func__, payload[0], payload[1]);
+ __func__,
+ payload[0],
+ payload[1]);
if (wakeup_flag) {
atomic_set(&ac->cmd_state, payload[1]);
wake_up(&ac->cmd_wait);
@@ -1825,6 +1847,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
&(session[session_id].session_lock),
flags);
return 0;
+ } else {
+ pr_err("%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
}
if (atomic_read(&ac->cmd_state) && wakeup_flag) {
atomic_set(&ac->cmd_state, 0);
@@ -1835,11 +1860,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
(uint32_t *)data->payload, ac->priv);
break;
case ASM_CMD_ADD_TOPOLOGIES:
- pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
- __func__, payload[0], payload[1]);
- if (payload[1] != 0) {
+ if (data->payload_size >=
+ 2 * sizeof(uint32_t) &&
+ payload[1] != 0) {
+ pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
+ __func__, payload[0], payload[1]);
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
- __func__, payload[0], payload[1]);
+ __func__, payload[0], payload[1]);
if (wakeup_flag) {
atomic_set(&ac->mem_state, payload[1]);
wake_up(&ac->mem_wait);
@@ -1858,8 +1885,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
(uint32_t *)data->payload, ac->priv);
break;
case ASM_DATA_EVENT_WATERMARK: {
- pr_debug("%s: Watermark opcode[0x%x] status[0x%x]",
- __func__, payload[0], payload[1]);
+ if (data->payload_size >= 2 * sizeof(uint32_t))
+ pr_debug("%s: Watermark opcode[0x%x] status[0x%x]",
+ __func__, payload[0], payload[1]);
+ else
+ pr_err("%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
break;
}
case ASM_STREAM_CMD_GET_PP_PARAMS_V2:
@@ -1871,11 +1902,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
/* error or malformed APR packet. Otherwise */
/* response will be returned as */
/* ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 */
- if (payload[1] != 0) {
- pr_err("%s: ASM get param error = %d, resuming\n",
- __func__, payload[1]);
- rtac_make_asm_callback(ac->session, payload,
+ if (data->payload_size >= 2 * sizeof(uint32_t)) {
+ if (payload[1] != 0) {
+ pr_err("%s: ASM get param error = %d, resuming\n",
+ __func__, payload[1]);
+ rtac_make_asm_callback(ac->session,
+ payload,
data->payload_size);
+ }
+ } else {
+ pr_err("%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
}
break;
default:
@@ -1892,9 +1929,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
switch (data->opcode) {
case ASM_DATA_EVENT_WRITE_DONE_V2:{
struct audio_port_data *port = &ac->port[IN];
- dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
- __func__, payload[0], payload[1],
- data->token);
+ if (data->payload_size >= 2 * sizeof(uint32_t))
+ dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
+ __func__, payload[0], payload[1],
+ data->token);
+ else
+ dev_err(ac->dev, "%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
if (ac->io_mode & SYNC_IO_MODE) {
if (port->buf == NULL) {
pr_err("%s: Unexpected Write Done\n",
@@ -1955,14 +1996,32 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
} else if (generic_get_data) {
generic_get_data->valid = 1;
if (generic_get_data->is_inband) {
- pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n",
- __func__, payload[1], payload[2], payload[3]);
- generic_get_data->size_in_ints = payload[3]>>2;
- for (i = 0; i < payload[3]>>2; i++) {
- generic_get_data->ints[i] =
- payload[4+i];
- pr_debug("%s: ASM callback val %i = %i\n",
- __func__, i, payload[4+i]);
+ if (data->payload_size >= 4 * sizeof(uint32_t))
+ pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n",
+ __func__,
+ payload[1],
+ payload[2],
+ payload[3]);
+ else
+ pr_err("%s: payload size of %x is less than expected.\n",
+ __func__,
+ data->payload_size);
+
+ if (data->payload_size >=
+ (4 + (payload[3]>>2))
+ * sizeof(uint32_t)) {
+ generic_get_data->size_in_ints =
+ payload[3]>>2;
+ for (i = 0; i < payload[3]>>2; i++) {
+ generic_get_data->ints[i] =
+ payload[4+i];
+ pr_debug("%s: ASM callback val %i = %i\n",
+ __func__, i,
+ payload[4+i]);
+ }
+ } else {
+ pr_err("%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
}
pr_debug("%s: callback size in ints = %i\n",
__func__,
@@ -2059,11 +2118,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
data->src_port, data->dest_port);
break;
case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
- dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
- __func__,
- payload[0], payload[1], payload[2]);
- ac->time_stamp = (uint64_t)(((uint64_t)payload[2] << 32) |
- payload[1]);
+ if (data->payload_size >= 3 * sizeof(uint32_t)) {
+ dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
+ __func__,
+ payload[0], payload[1], payload[2]);
+ ac->time_stamp =
+ (uint64_t)(((uint64_t)payload[2] << 32) |
+ payload[1]);
+ } else {
+ dev_err(ac->dev, "%s: payload size of %x is less than expected.n",
+ __func__, data->payload_size);
+ }
if (atomic_cmpxchg(&ac->time_flag, 1, 0))
wake_up(&ac->time_wait);
break;
@@ -2073,19 +2138,30 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
__func__, ac->session,
data->opcode, data->token,
data->src_port, data->dest_port);
- pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n",
- __func__,
- payload[0], payload[1], payload[2],
- payload[3]);
+ if (data->payload_size >= 4 * sizeof(uint32_t))
+ pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n",
+ __func__,
+ payload[0], payload[1], payload[2],
+ payload[3]);
+ else
+ pr_debug("%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
break;
case ASM_SESSION_CMDRSP_GET_MTMX_STRTR_PARAMS_V2:
q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
break;
case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2:
- pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
- __func__, ac->session, payload[0], payload[2],
+ if (data->payload_size >= 3 * sizeof(uint32_t))
+ pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
+ __func__, ac->session,
+ payload[0], payload[2],
payload[1]);
- if (payload[0] == 0) {
+ else
+ pr_err("%s: payload size of %x is less than expected.\n",
+ __func__, data->payload_size);
+ if (payload[0] == 0 &&
+ data->payload_size >=
+ 2 * sizeof(uint32_t)) {
atomic_set(&ac->cmd_state, 0);
/* ignore msw, as a delay that large shouldn't happen */
ac->path_delay = payload[1];
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index ec734722b415..9b5d7705b478 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 2019 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
@@ -161,7 +161,8 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (data->opcode == LSM_DATA_EVENT_READ_DONE) {
struct lsm_cmd_read_done read_done;
token = data->token;
- if (data->payload_size > sizeof(read_done)) {
+ if (data->payload_size > sizeof(read_done) ||
+ data->payload_size < 6 * sizeof(payload[0])) {
pr_err("%s: read done error payload size %d expected size %zd\n",
__func__, data->payload_size,
sizeof(read_done));
@@ -179,6 +180,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (client->cb)
client->cb(data->opcode, data->token,
(void *)&read_done,
+ sizeof(read_done),
client->priv);
return 0;
} else if (data->opcode == APR_BASIC_RSP_RESULT) {
@@ -204,6 +206,10 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
__func__, token, client->session);
return -EINVAL;
}
+ if (data->payload_size < 2 * sizeof(payload[0])) {
+ pr_err("%s: payload has invalid size[%d]\n",
+ __func__, data->payload_size);
+ }
client->cmd_err_code = payload[1];
if (client->cmd_err_code)
pr_err("%s: cmd 0x%x failed status %d\n",
@@ -224,7 +230,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (client->cb)
client->cb(data->opcode, data->token, data->payload,
- client->priv);
+ data->payload_size, client->priv);
return 0;
}
@@ -1129,6 +1135,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
pr_debug("%s: SSR event received 0x%x, event 0x%x,\n"
"proc 0x%x SID 0x%x\n", __func__, data->opcode,
data->reset_event, data->reset_proc, sid);
+ if (sid < LSM_MIN_SESSION_ID || sid > LSM_MAX_SESSION_ID)
+ pr_err("%s: Invalid session %d\n", __func__, sid);
lsm_common.common_client[sid].lsm_cal_phy_addr = 0;
cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
lsm_common.cal_data);
@@ -1190,7 +1198,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
}
if (client->cb)
client->cb(data->opcode, data->token,
- data->payload, client->priv);
+ data->payload, data->payload_size,
+ client->priv);
return 0;
}