diff options
author | Eric Caruso <ejcaruso@chromium.org> | 2018-02-21 13:49:34 -0800 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2018-02-23 12:33:37 +0100 |
commit | 402559bb62bb44aa146b1c170bb86812d6d514a9 (patch) | |
tree | 7504db5ca85661001ac19b7e4f40122948d5293f /src | |
parent | d416ea491d88b2b3bb4e5cd8077e0b758bcfad2e (diff) |
mm-base-manager: ref MMDevice before releasing port
Releasing the port on the device looks benign but because it emits
a signal, it could call device_context_port_released and unref the
MMDevice in port_context_unref. This means the MMDevice might be
disposed before we get to the g_object_ref and the subsequent call
to g_hash_table_remove will try to hash a null string, which makes
MM crash.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-manager.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c index 4b92ab0b..7738ce0d 100644 --- a/src/mm-base-manager.c +++ b/src/mm-base-manager.c @@ -220,28 +220,28 @@ device_removed (MMBaseManager *self, /* Handle tty/net/wdm port removal */ device = find_device_by_port (self, kernel_device); if (device) { + /* The callbacks triggered when the port is released or device support is + * cancelled may end up unreffing the device or removing it from the HT, and + * so in order to make sure the reference is still valid when we call + * support_check_cancel() and g_hash_table_remove(), we hold a full reference + * ourselves. */ + g_object_ref (device); + mm_info ("(%s/%s): released by device '%s'", subsys, name, mm_device_get_uid (device)); mm_device_release_port (device, kernel_device); /* If port probe list gets empty, remove the device object iself */ if (!mm_device_peek_port_probe_list (device)) { - /* The callback triggered when the device support is cancelled may end up - * removing the device from the HT, and that was the last full reference - * we kept. So, in order to make sure the reference is still valid after - * support_check_cancel(), we hold a full reference ourselves. */ mm_dbg ("Removing empty device '%s'", mm_device_get_uid (device)); - g_object_ref (device); - { - if (mm_plugin_manager_device_support_check_cancel (self->priv->plugin_manager, device)) - mm_dbg ("Device support check has been cancelled"); - - /* The device may have already been removed from the tracking HT, we - * just try to remove it and if it fails, we ignore it */ - mm_device_remove_modem (device); - g_hash_table_remove (self->priv->devices, mm_device_get_uid (device)); - } - g_object_unref (device); + if (mm_plugin_manager_device_support_check_cancel (self->priv->plugin_manager, device)) + mm_dbg ("Device support check has been cancelled"); + + /* The device may have already been removed from the tracking HT, we + * just try to remove it and if it fails, we ignore it */ + mm_device_remove_modem (device); + g_hash_table_remove (self->priv->devices, mm_device_get_uid (device)); } + g_object_unref (device); } return; |