From 9c09cbdbb532b2e6c7b466178a82ac8b0d18c718 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Sat, 30 Jun 2018 19:57:10 +0530 Subject: [PATCH] dsp: q6lsm: Avoid null pointer access in SSR Synchronize both contexts of SSR and SVA close to avoid access of client handle after free. Check whether the client is valid or not when retrieved from private data in q6lsm_callback along with NULL check to avoid invalidated pointer access. Change-Id: I51c13cd79fd947c624bf0cade4c93a3fdf07353e Signed-off-by: Aditya Bavanari --- dsp/q6lsm.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c index f34187d1fdfc..46e20132f180 100644 --- a/dsp/q6lsm.c +++ b/dsp/q6lsm.c @@ -75,6 +75,8 @@ struct lsm_common { }; static struct lsm_common lsm_common; +static DEFINE_MUTEX(session_lock); + /* * mmap_handle_p can point either client->sound_model.mem_map_handle or * lsm_common.mmap_handle_for_cal. @@ -95,6 +97,24 @@ static int q6lsm_memory_map_regions(struct lsm_client *client, static int q6lsm_memory_unmap_regions(struct lsm_client *client, uint32_t handle); +static int q6lsm_get_session_id_from_lsm_client(struct lsm_client *client) +{ + int n; + + for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) { + if (lsm_session[n] == client) + return n; + } + pr_err("%s: cannot find matching lsm client. client = %pa\n", + __func__, client); + return LSM_INVALID_SESSION_ID; +} + +static bool q6lsm_is_valid_lsm_client(struct lsm_client *client) +{ + return q6lsm_get_session_id_from_lsm_client(client) ? 1 : 0; +} + static int q6lsm_callback(struct apr_client_data *data, void *priv) { struct lsm_client *client = (struct lsm_client *)priv; @@ -113,6 +133,13 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv) __func__, data->opcode, data->reset_event, data->reset_proc); + mutex_lock(&session_lock); + if (!client || !q6lsm_is_valid_lsm_client(client)) { + pr_err("%s: client already freed/invalid, return\n", + __func__); + mutex_unlock(&session_lock); + return 0; + } apr_reset(client->apr); client->apr = NULL; atomic_set(&client->cmd_state, CMD_STATE_CLEARED); @@ -122,6 +149,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv) mutex_lock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock); lsm_common.set_custom_topology = 1; mutex_unlock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock); + mutex_unlock(&session_lock); return 0; } @@ -334,6 +362,7 @@ void q6lsm_client_free(struct lsm_client *client) pr_err("%s: Invalid Session %d\n", __func__, client->session); return; } + mutex_lock(&session_lock); apr_deregister(client->apr); client->mmap_apr = NULL; q6lsm_session_free(client); @@ -341,6 +370,7 @@ void q6lsm_client_free(struct lsm_client *client) mutex_destroy(&client->cmd_lock); kfree(client); client = NULL; + mutex_unlock(&session_lock); } EXPORT_SYMBOL(q6lsm_client_free);