diff options
author | Robert Lee <lerobert@google.com> | 2019-11-06 19:05:15 +0800 |
---|---|---|
committer | Harrison Lingren <hlingren@google.com> | 2020-01-06 18:40:07 +0000 |
commit | 972a37bccd990dae69414c545534f705ca25f1f2 (patch) | |
tree | 32dcf2698b22e406b84d0bf4d701566f8f3fadf8 | |
parent | 33947067e30ceac232d167c12af9fb523b0fa79d (diff) | |
download | msm-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.c | 17 |
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; |