simfs: Fix crash in sim_fs_op_free

If an operation is in progress and an operation is canceled, we don't
actually destroy it, but simply clear out the callback.  In the case of
a context being destroyed, the operation is left on the simfs op_q with
a dangling pointer to the already freed context.  So the current logic
in sim_fs_op_free tries to access invalid memory.

Fix this by performing the watch operations in sim_fs_end_current
instead and setting the context pointer appropriately.
This commit is contained in:
Denis Kenzior 2018-03-29 09:46:22 -05:00
parent db9b292f92
commit 8b8a760644
1 changed files with 6 additions and 5 deletions

View File

@ -95,11 +95,6 @@ struct sim_fs {
static void sim_fs_op_free(gpointer pointer)
{
struct sim_fs_op *node = pointer;
struct sim_fs *fs = node->context->fs;
/* only release the session if there are no pending reads */
if (fs->watch_id && g_queue_is_empty(fs->op_q))
__ofono_sim_remove_session_watch(fs->session, fs->watch_id);
g_free(node->buffer);
g_free(node);
@ -127,6 +122,9 @@ void sim_fs_free(struct sim_fs *fs)
while (fs->contexts)
sim_fs_context_free(fs->contexts->data);
if (fs->watch_id)
__ofono_sim_remove_session_watch(fs->session, fs->watch_id);
g_free(fs);
}
@ -197,6 +195,7 @@ void sim_fs_context_free(struct ofono_sim_context *context)
if (n == 0) {
op->cb = NULL;
op->context = NULL;
n += 1;
continue;
@ -272,6 +271,8 @@ static void sim_fs_end_current(struct sim_fs *fs)
if (g_queue_get_length(fs->op_q) > 0)
fs->op_source = g_idle_add(sim_fs_op_next, fs);
else if (fs->watch_id) /* release the session if no pending reads */
__ofono_sim_remove_session_watch(fs->session, fs->watch_id);
if (fs->fd != -1) {
TFR(close(fs->fd));