diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 95a32796a864..cd2466fd110f 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -542,7 +542,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, */ spin_lock(&proc_priv->ctxt_count_lock); if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) { - KGSL_DRV_ERR(device, + KGSL_DRV_ERR_RATELIMIT(device, "Per process context limit reached for pid %u", dev_priv->process_priv->pid); spin_unlock(&proc_priv->ctxt_count_lock); diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 1ec06cb07523..99903c0e7944 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -3717,7 +3717,12 @@ err_no_work: for (i = 0; !IS_ERR_OR_NULL(device->response_pkt) && i < num_responses; ++i) { struct msm_vidc_cb_info *r = &device->response_pkt[i]; - + if (!__core_in_valid_state(device)) { + dprintk(VIDC_ERR, + "Ignore responses from %d to %d as device is in invalid state", + (i + 1), num_responses); + break; + } device->callback(r->response_type, &r->response); } diff --git a/drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.c b/drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.c index 334e705ca8f1..30a81ba39001 100644 --- a/drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.c +++ b/drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, 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 @@ -507,6 +507,12 @@ static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv) uint32_t token; uint32_t *payload = data->payload; + if (data->payload_size < (2 * sizeof(uint32_t))) { + pr_err("%s: payload has invalid size[%d]\n", __func__, + data->payload_size); + return -EINVAL; + } + pr_debug("%s: ptr0[0x%x]; ptr1[0x%x]; opcode[0x%x]\n", __func__, payload[0], payload[1], data->opcode); pr_debug("%s: token[0x%x]; payload_size[%d]; src[%d]; dest[%d];\n", @@ -567,6 +573,11 @@ static int32_t q6usm_callback(struct apr_client_data *data, void *priv) } if (data->opcode == APR_BASIC_RSP_RESULT) { + if (data->payload_size < (2 * sizeof(uint32_t))) { + pr_err("%s: payload has invalid size[%d]\n", __func__, + data->payload_size); + return -EINVAL; + } /* status field check */ if (payload[1]) { pr_err("%s: wrong response[%d] on cmd [%d]\n", @@ -630,6 +641,14 @@ static int32_t q6usm_callback(struct apr_client_data *data, void *priv) opcode = Q6USM_EVENT_READ_DONE; spin_lock_irqsave(&port->dsp_lock, dsp_flags); + if (data->payload_size < + (sizeof(uint32_t)*(READDONE_IDX_STATUS + 1))) { + pr_err("%s: Invalid payload size for READDONE[%d]\n", + __func__, data->payload_size); + spin_unlock_irqrestore(&port->dsp_lock, + dsp_flags); + return -EINVAL; + } if (payload[READDONE_IDX_STATUS]) { pr_err("%s: wrong READDONE[%d]; token[%d]\n", __func__, @@ -675,6 +694,12 @@ static int32_t q6usm_callback(struct apr_client_data *data, void *priv) struct us_port_data *port = &usc->port[IN]; opcode = Q6USM_EVENT_WRITE_DONE; + if (data->payload_size < + (sizeof(uint32_t)*(WRITEDONE_IDX_STATUS + 1))) { + pr_err("%s: Invalid payload size for WRITEDONE[%d]\n", + __func__, data->payload_size); + return -EINVAL; + } if (payload[WRITEDONE_IDX_STATUS]) { pr_err("%s: wrong WRITEDONE_IDX_STATUS[%d]\n", __func__, diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index fae06806b7db..454a897c19ab 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -75,6 +75,8 @@ module_param(qmi_timeout, ulong, 0600); #define ICNSS_MAX_PROBE_CNT 2 +#define PROBE_TIMEOUT 5000 + #define icnss_ipc_log_string(_x...) do { \ if (icnss_ipc_log_context) \ ipc_log_string(icnss_ipc_log_context, _x); \ @@ -299,6 +301,7 @@ enum icnss_driver_state { ICNSS_FW_DOWN, ICNSS_DRIVER_UNLOADING, ICNSS_REJUVENATE, + ICNSS_BLOCK_SHUTDOWN, }; struct ce_irq_list { @@ -491,6 +494,7 @@ static struct icnss_priv { u8 requesting_sub_system; u16 line_number; char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1]; + struct completion unblock_shutdown; } *penv; #ifdef CONFIG_ICNSS_DEBUG @@ -1178,6 +1182,21 @@ bool icnss_is_fw_ready(void) } EXPORT_SYMBOL(icnss_is_fw_ready); +void icnss_block_shutdown(bool status) +{ + if (!penv) + return; + + if (status) { + set_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state); + reinit_completion(&penv->unblock_shutdown); + } else { + clear_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state); + complete(&penv->unblock_shutdown); + } +} +EXPORT_SYMBOL(icnss_block_shutdown); + bool icnss_is_fw_down(void) { if (!penv) @@ -2203,6 +2222,7 @@ static int icnss_call_driver_probe(struct icnss_priv *priv) icnss_hw_power_on(priv); + icnss_block_shutdown(true); while (probe_cnt < ICNSS_MAX_PROBE_CNT) { ret = priv->ops->probe(&priv->pdev->dev); probe_cnt++; @@ -2212,9 +2232,11 @@ static int icnss_call_driver_probe(struct icnss_priv *priv) if (ret < 0) { icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n", ret, priv->state, probe_cnt); + icnss_block_shutdown(false); goto out; } + icnss_block_shutdown(false); set_bit(ICNSS_DRIVER_PROBED, &priv->state); return 0; @@ -2350,6 +2372,7 @@ static int icnss_driver_event_register_driver(void *data) if (ret) goto out; + icnss_block_shutdown(true); while (probe_cnt < ICNSS_MAX_PROBE_CNT) { ret = penv->ops->probe(&penv->pdev->dev); probe_cnt++; @@ -2359,9 +2382,11 @@ static int icnss_driver_event_register_driver(void *data) if (ret) { icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n", ret, penv->state, probe_cnt); + icnss_block_shutdown(false); goto power_off; } + icnss_block_shutdown(false); set_bit(ICNSS_DRIVER_PROBED, &penv->state); return 0; @@ -2584,6 +2609,13 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, if (code != SUBSYS_BEFORE_SHUTDOWN) return NOTIFY_OK; + if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && + test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) { + if (!wait_for_completion_timeout(&priv->unblock_shutdown, + PROBE_TIMEOUT)) + icnss_pr_err("wlan driver probe timeout\n"); + } + if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed) { ret = wlfw_send_modem_shutdown_msg(); if (ret) @@ -3980,6 +4012,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_DRIVER_UNLOADING: seq_puts(s, "DRIVER UNLOADING"); + continue; + case ICNSS_BLOCK_SHUTDOWN: + seq_puts(s, "BLOCK SHUTDOWN"); } seq_printf(s, "UNKNOWN-%d", i); @@ -4651,6 +4686,8 @@ static int icnss_probe(struct platform_device *pdev) penv = priv; + init_completion(&priv->unblock_shutdown); + icnss_pr_info("Platform driver probed successfully\n"); return 0; @@ -4673,6 +4710,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_debugfs_destroy(penv); + complete_all(&penv->unblock_shutdown); + icnss_modem_ssr_unregister_notifier(penv); destroy_ramdump_device(penv->msa0_dump_dev); diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index f01ab2499a75..0a49a322c9da 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2018, 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 @@ -68,8 +68,9 @@ static void *dummy_q6_mvm; static void *dummy_q6_cvs; dev_t device_num; +static struct mutex session_lock; static spinlock_t voicesvc_lock; -static bool is_released; +static bool is_released = 1; static int voice_svc_dummy_reg(void); static int voice_svc_dummy_dereg(void); @@ -645,14 +646,23 @@ static int voice_svc_dummy_dereg(void) static int voice_svc_open(struct inode *inode, struct file *file) { struct voice_svc_prvt *prtd = NULL; + int ret = 0; pr_debug("%s\n", __func__); + 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)); @@ -676,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) @@ -810,6 +822,7 @@ static int voice_svc_probe(struct platform_device *pdev) } pr_debug("%s: Device created\n", __func__); spin_lock_init(&voicesvc_lock); + mutex_init(&session_lock); goto done; add_err: @@ -832,6 +845,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/include/linux/perf_event.h b/include/linux/perf_event.h index f501b8c0de4e..efce166a9f17 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -231,7 +231,7 @@ struct pmu { int capabilities; int * __percpu pmu_disable_count; - struct perf_cpu_context * __percpu pmu_cpu_context; + struct perf_cpu_context __percpu *pmu_cpu_context; atomic_t exclusive_cnt; /* < 0: cpu; > 0: tsk */ int task_ctx_nr; int hrtimer_interval_ms; diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h index 85ec8beb3157..010f29db8d48 100644 --- a/include/soc/qcom/icnss.h +++ b/include/soc/qcom/icnss.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -157,10 +157,5 @@ extern bool icnss_is_rejuvenate(void); extern int icnss_set_wlan_mac_address(const u8 *in, const uint32_t len); extern u8 *icnss_get_wlan_mac_address(struct device *dev, uint32_t *num); extern int icnss_trigger_recovery(struct device *dev); -extern void cnss_set_cc_source(enum cnss_cc_src cc_source); -extern enum cnss_cc_src cnss_get_cc_source(void); -extern int icnss_get_driver_load_cnt(void); -extern void icnss_increment_driver_load_cnt(void); -extern void icnss_set_cc_source(enum cnss_cc_src cc_source); -extern enum cnss_cc_src icnss_get_cc_source(void); +extern void icnss_block_shutdown(bool status); #endif /* _ICNSS_WLAN_H_ */ diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h index c046cd468b49..4600b0445955 100644 --- a/include/sound/q6lsm.h +++ b/include/sound/q6lsm.h @@ -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 @@ -26,7 +26,7 @@ #define LSM_MAX_NUM_CHANNELS 8 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/kernel/events/core.c b/kernel/events/core.c index a8f984b4fcff..3e6e5eb3e4d2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -9654,13 +9654,26 @@ static void __perf_event_stop_swclock(void *__info) static void perf_event_exit_cpu_context(int cpu) { + struct perf_cpu_context *cpuctx; struct perf_event_context *ctx; + unsigned long flags; struct pmu *pmu; int idx; idx = srcu_read_lock(&pmus_srcu); list_for_each_entry_rcu(pmu, &pmus, entry) { - ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx; + cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); + ctx = &cpuctx->ctx; + + /* Cancel the mux hrtimer to avoid CPU migration */ + if (pmu->task_ctx_nr != perf_sw_context) { + raw_spin_lock_irqsave(&cpuctx->hrtimer_lock, flags); + hrtimer_cancel(&cpuctx->hrtimer); + cpuctx->hrtimer_active = 0; + raw_spin_unlock_irqrestore(&cpuctx->hrtimer_lock, + flags); + } + mutex_lock(&ctx->mutex); /* * If keeping events across hotplugging is supported, do not diff --git a/lib/qmi_encdec.c b/lib/qmi_encdec.c index 72b506bececc..9d5c446830ed 100644 --- a/lib/qmi_encdec.c +++ b/lib/qmi_encdec.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 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 @@ -710,8 +710,8 @@ static int qmi_decode_string_elem(struct elem_info *ei_array, void *buf_dst, decoded_bytes += rc; } - if (string_len > temp_ei->elem_len) { - pr_err("%s: String len %d > Max Len %d\n", + if (string_len >= temp_ei->elem_len) { + pr_err("%s: String len %d >= Max Len %d\n", __func__, string_len, temp_ei->elem_len); return -ETOOSMALL; } else if (string_len > tlv_len) { diff --git a/net/wireless/db.txt b/net/wireless/db.txt index bc7a70a76685..326a6f29c6bd 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -579,8 +579,8 @@ country IT: DFS-ETSI country JM: DFS-FCC (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (24), AUTO-BW - (5250 - 5330 @ 80), (24), DFS, AUTO-BW - (5490 - 5730 @ 160), (24), DFS + (5250 - 5330 @ 80), (24), AUTO-BW + (5490 - 5730 @ 160), (24) (5735 - 5835 @ 80), (30) # 60 gHz band channels 1-3, FCC (57240 - 63720 @ 2160), (40) diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c index 5c4e145c2e31..9b0918cc579f 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 @@ -195,7 +195,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; @@ -263,6 +264,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; @@ -272,6 +279,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; @@ -281,6 +294,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, break; case LSM_SESSION_EVENT_DETECTION_STATUS_V3: + if (client_size < 2 * (sizeof(uint32_t) + sizeof(uint8_t))) { + dev_err(rtd->dev, + "%s: client_size has invalid size[%d]\n", + __func__, client_size); + return; + } event_ts_lsw = ((uint32_t *)payload)[0]; event_ts_msw = ((uint32_t *)payload)[1]; status = (uint16_t)((uint8_t *)payload)[8]; @@ -318,12 +337,22 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, 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/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c index 29a5fd18081a..6f4653a07dad 100644 --- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -1020,6 +1020,13 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, } event_data = (struct msm_adsp_event_data *)payload; + if (event_data->payload_len < sizeof(struct msm_adsp_event_data)) { + pr_err("%s: event_data size of %x is less than expected.\n", + __func__, event_data->payload_len); + ret = -EINVAL; + goto done; + } + kctl->info(kctl, &kctl_info); if (event_data->payload_len > diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index b87e7f886fa6..20c933b80c66 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, 2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -583,7 +583,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) ret = afe_lpass_resources_callback(data); atomic_set(&this_afe.state, 0); - wake_up(&this_afe.wait[data->token]); + if (afe_token_is_valid(data->token)) + wake_up(&this_afe.wait[data->token]); + else + return -EINVAL; if (!ret) { return ret; } diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index fd74f157d6f8..79f1bc3be655 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -2180,8 +2180,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) buf_index = asm_token._token.buf_index; if (buf_index < 0 || buf_index >= port->max_buf_cnt) { - pr_debug("%s: Invalid buffer index %u\n", - __func__, buf_index); + pr_err("%s: Invalid buffer index %u\n", + __func__, buf_index); spin_unlock_irqrestore(&port->dsp_lock, dsp_flags); spin_unlock_irqrestore( @@ -2300,8 +2300,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) spin_lock_irqsave(&port->dsp_lock, dsp_flags); buf_index = asm_token._token.buf_index; if (buf_index < 0 || buf_index >= port->max_buf_cnt) { - pr_debug("%s: Invalid buffer index %u\n", - __func__, buf_index); + pr_err("%s: Invalid buffer index %u\n", + __func__, buf_index); spin_unlock_irqrestore(&port->dsp_lock, dsp_flags); spin_unlock_irqrestore( diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c index a0fa233bb71e..d926623eaa19 100644 --- a/sound/soc/msm/qdsp6v2/q6lsm.c +++ b/sound/soc/msm/qdsp6v2/q6lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, Linux Foundation. All rights reserved. + * Copyright (c) 2013-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 @@ -127,7 +127,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)); @@ -145,6 +146,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) { @@ -171,6 +173,11 @@ 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); + return -EINVAL; + } client->cmd_err_code = payload[1]; if (client->cmd_err_code) pr_err("%s: cmd 0x%x failed status %d\n", @@ -191,7 +198,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; } @@ -1365,6 +1372,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); @@ -1426,7 +1435,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; } diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index 69189140c936..3193dd0de140 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -6782,6 +6782,11 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data; if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) { + if (v->shmem_info.sh_buf.buf[1].size < + ((3 * sizeof(uint32_t)) + cvs_voc_pkt[2])) { + pr_err("%s: invalid voc pkt size\n", __func__); + return -EINVAL; + } /* cvs_voc_pkt[0] contains tx timestamp */ common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3], cvs_voc_pkt[2],