diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-10-05 23:29:13 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-10-05 23:59:26 +0200 |
commit | 3c3c9aa10f5921193cede586eeba9ba9591bdd76 (patch) | |
tree | d52a79d9e5277fdc4325c6eb2b0e6d80e83301f3 | |
parent | 574ba880e5050e91ae1a67795f7240d384582a74 (diff) | |
download | ModemManager-3c3c9aa10f5921193cede586eeba9ba9591bdd76.tar.gz |
plugin-manager: ensure valid reference during cancellation
Cancelling the port_context->cancellable may end up finishing the
async task and completing the last reference of the port
context. Avoid that by making sure we hold a valid reference for as
long as we may need it.
==2277== Invalid read of size 4
==2277== at 0x14ACE2: port_context_cancel (mm-plugin-manager.c:547)
==2277== by 0x14C32E: device_context_port_released (mm-plugin-manager.c:1142)
==2277== by 0x83831C7: ffi_call_unix64 (in /usr/lib/libffi.so.6.0.4)
==2277== by 0x8382C29: ffi_call (in /usr/lib/libffi.so.6.0.4)
==2277== by 0x64506A8: g_cclosure_marshal_generic (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x644FEAC: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x64624AD: ??? (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x646AC84: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x646B69E: g_signal_emit (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x1483E7: mm_device_release_port (mm-device.c:196)
==2277== by 0x145D5D: device_removed (mm-base-manager.c:217)
==2277== by 0x1464A9: handle_kernel_event (mm-base-manager.c:401)
==2277== Address 0xf677d18 is 88 bytes inside a block of size 96 free'd
==2277== at 0x4C2E14B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2277== by 0x14A1B7: port_context_unref (mm-plugin-manager.c:234)
==2277== by 0x14AB51: plugin_supports_port_ready (mm-plugin-manager.c:492)
==2277== by 0x612FD52: ??? (in /usr/lib/libgio-2.0.so.0.5200.3)
==2277== by 0x6130775: ??? (in /usr/lib/libgio-2.0.so.0.5200.3)
==2277== by 0x1AFDF8: port_probe_run_ready (mm-plugin.c:624)
==2277== by 0x612FD52: ??? (in /usr/lib/libgio-2.0.so.0.5200.3)
==2277== by 0x6130775: ??? (in /usr/lib/libgio-2.0.so.0.5200.3)
==2277== by 0x6131367: g_task_return_error_if_cancelled (in /usr/lib/libgio-2.0.so.0.5200.3)
==2277== by 0x1A9EDA: port_probe_task_return_error_if_cancelled (mm-port-probe.c:109)
==2277== by 0x1ABCD2: serial_probe_at_parse_response (mm-port-probe.c:900)
==2277== by 0x611E475: g_simple_async_result_complete (in /usr/lib/libgio-2.0.so.0.5200.3)
==2277== Block was alloc'd at
==2277== at 0x4C2CE5F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2277== by 0x66E3028: g_malloc (in /usr/lib/libglib-2.0.so.0.5200.3)
==2277== by 0x66FAB25: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.5200.3)
==2277== by 0x66FAFB8: g_slice_alloc0 (in /usr/lib/libglib-2.0.so.0.5200.3)
==2277== by 0x14B18D: port_context_new (mm-plugin-manager.c:649)
==2277== by 0x14C4A7: device_context_port_grabbed (mm-plugin-manager.c:1182)
==2277== by 0x83831C7: ffi_call_unix64 (in /usr/lib/libffi.so.6.0.4)
==2277== by 0x8382C29: ffi_call (in /usr/lib/libffi.so.6.0.4)
==2277== by 0x64506A8: g_cclosure_marshal_generic (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x644FEAC: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x64624AD: ??? (in /usr/lib/libgobject-2.0.so.0.5200.3)
==2277== by 0x646AC84: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.5200.3)
(cherry picked from commit bbe50645916c4596cf7c7b309aac267d396801b8)
-rw-r--r-- | src/mm-plugin-manager.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c index 22965fdb8..35a01122c 100644 --- a/src/mm-plugin-manager.c +++ b/src/mm-plugin-manager.c @@ -540,25 +540,28 @@ port_context_cancel (PortContext *port_context) mm_dbg ("[plugin manager) task %s: cancellation requested", port_context->name); - /* The port context is cancelled now */ - g_cancellable_cancel (port_context->cancellable); - - /* If the task was deferred, we can cancel and complete it right away */ - if (port_context->defer_id) { - g_source_remove (port_context->defer_id); - port_context->defer_id = 0; - port_context_complete (port_context); - return TRUE; - } + /* Make sure we hold a port context reference while cancelling, as the + * cancellable signal handlers may end up unref-ing our last reference + * otherwise. */ + port_context_ref (port_context); + { + /* The port context is cancelled now */ + g_cancellable_cancel (port_context->cancellable); - /* If the task was deferred until a result is suggested, we can also - * complete it right away */ - if (port_context->defer_until_suggested) { - port_context_complete (port_context); - return TRUE; + /* If the task was deferred, we can cancel and complete it right away */ + if (port_context->defer_id) { + g_source_remove (port_context->defer_id); + port_context->defer_id = 0; + port_context_complete (port_context); + } + /* If the task was deferred until a result is suggested, we can also + * complete it right away */ + else if (port_context->defer_until_suggested) + port_context_complete (port_context); + /* else, the task may be currently checking support with a given plugin */ } + port_context_unref (port_context); - /* The task may be currently checking support with a given plugin */ return TRUE; } |