mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 08:36:12 -04:00
msm: synx: validate external callback
Validate the external callback to prevent acting on delayed invocations, after the corresponding handle has been released and reallocated by the clients. Change also avoids release of memory shared with external callback if the callback de-registration fails. This avoids double free issue if callback has been queued up for dispatch during the cleanup. Change-Id: Ib784c8a630a7c45ace946edab34e36ab1aec1869 Signed-off-by: Sumukh Hallymysore Ravindra <shallymy@codeaurora.org>
This commit is contained in:
parent
31ef58ab90
commit
abcc12b931
2 changed files with 51 additions and 8 deletions
|
|
@ -16,6 +16,40 @@
|
|||
|
||||
struct synx_device *synx_dev;
|
||||
|
||||
static int synx_validate_callback(
|
||||
struct synx_coredata *synx_obj,
|
||||
s32 sync_id,
|
||||
void *data)
|
||||
{
|
||||
u32 i;
|
||||
int rc = -EINVAL;
|
||||
struct synx_bind_desc *bind_desc = NULL;
|
||||
|
||||
if (!synx_obj)
|
||||
return -EINVAL;
|
||||
|
||||
/* need to validate the callback
|
||||
* as it could be dispatched and/or
|
||||
* scheduled late, after the handle
|
||||
* has been released and re-allocated.
|
||||
*/
|
||||
spin_lock_bh(&synx_obj->lock);
|
||||
for (i = 0; i < synx_obj->num_bound_synxs; i++) {
|
||||
bind_desc = &synx_obj->bound_synxs[i];
|
||||
if ((sync_id ==
|
||||
bind_desc->external_desc.id[0]) &&
|
||||
(data == bind_desc->external_data)) {
|
||||
rc = 0;
|
||||
pr_debug("callback validation success %d\n",
|
||||
sync_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&synx_obj->lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void synx_external_callback(s32 sync_obj, int status, void *data)
|
||||
{
|
||||
struct synx_coredata *synx_obj;
|
||||
|
|
@ -29,8 +63,11 @@ void synx_external_callback(s32 sync_obj, int status, void *data)
|
|||
}
|
||||
|
||||
client = synx_get_client(bind_data->session_id);
|
||||
if (!client)
|
||||
if (!client) {
|
||||
pr_err("invalid payload content from sync external obj %d\n",
|
||||
sync_obj);
|
||||
goto free;
|
||||
}
|
||||
|
||||
synx_obj = synx_util_acquire_object(client, bind_data->h_synx);
|
||||
if (!synx_obj) {
|
||||
|
|
@ -39,12 +76,19 @@ void synx_external_callback(s32 sync_obj, int status, void *data)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (synx_validate_callback(synx_obj, sync_obj, data)) {
|
||||
pr_err("[sess: %u] stale callback from external obj %d handle %d\n",
|
||||
client->id, sync_obj, bind_data->h_synx);
|
||||
goto release;
|
||||
}
|
||||
|
||||
pr_debug("[sess: %u] external callback from %d on handle %d\n",
|
||||
client->id, sync_obj, bind_data->h_synx);
|
||||
if (synx_signal_core(synx_obj, status, true, sync_obj))
|
||||
pr_err("[sess: %u] signal callback failed for handle %d\n",
|
||||
client->id, bind_data->h_synx);
|
||||
|
||||
release:
|
||||
synx_util_release_object(client, bind_data->h_synx);
|
||||
fail:
|
||||
synx_put_client(client);
|
||||
|
|
|
|||
|
|
@ -139,17 +139,16 @@ void synx_util_object_destroy(struct synx_coredata *synx_obj)
|
|||
bind_ops = synx_util_get_bind_ops(type);
|
||||
rc = bind_ops->deregister_callback(
|
||||
synx_external_callback, data, sync_id);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
pr_err("de-registration fail id: %d, type: %u, err: %d\n",
|
||||
sync_id, type, rc);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* release the memory allocated for external data.
|
||||
* It is safe to release this memory as external cb
|
||||
* has been already deregistered before this.
|
||||
* even if deregistration fails, it implies the
|
||||
* external fence might have been cleaned up already
|
||||
* or in some bad state. Have to release cb data
|
||||
* at this point or else will lead to memory leak.
|
||||
* It is safe to release this memory
|
||||
* only if deregistration is successful.
|
||||
*/
|
||||
kfree(data);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue